]> git.sur5r.net Git - openldap/blob - servers/slapd/overlays/rwm.c
Added ppolicy_hide_lockout keyword
[openldap] / servers / slapd / overlays / rwm.c
1 /* rwm.c - rewrite/remap operations */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2003-2004 The OpenLDAP Foundation.
6  * Portions Copyright 2003 Pierangelo Masarati.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
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>.
16  */
17
18 #include "portable.h"
19
20 #ifdef SLAPD_OVER_RWM
21
22 #include <stdio.h>
23
24 #include "slap.h"
25 #include "rwm.h"
26
27 static int
28 rwm_op_dn_massage( Operation *op, SlapReply *rs, void *cookie )
29 {
30         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
31         struct ldaprwmap        *rwmap = 
32                         (struct ldaprwmap *)on->on_bi.bi_private;
33
34         struct berval           dn, ndn, mdn = { 0, NULL };
35         int                     rc = 0;
36         dncookie                dc;
37
38         /*
39          * Rewrite the bind dn if needed
40          */
41         dc.rwmap = rwmap;
42 #ifdef ENABLE_REWRITE
43         dc.conn = op->o_conn;
44         dc.rs = rs;
45         dc.ctx = (char *)cookie;
46 #else
47         dc.tofrom = ((int *)cookie)[0];
48         dc.normalized = 0;
49 #endif
50
51         rc = rwm_dn_massage( &dc, &op->o_req_dn, &mdn );
52         if ( rc != LDAP_SUCCESS ) {
53                 return rc;
54         }
55
56         if ( mdn.bv_val == op->o_req_dn.bv_val ) {
57                 return LDAP_SUCCESS;
58         }
59
60         rc = dnPrettyNormal( NULL, &mdn, &dn, &ndn, op->o_tmpmemctx );
61         if ( rc != LDAP_SUCCESS ) {
62                 return rc;
63         }
64
65         if ( mdn.bv_val != dn.bv_val ) {
66                 ch_free( mdn.bv_val );
67         }
68
69         op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );
70         op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
71
72         op->o_req_dn = dn;
73         op->o_req_ndn = ndn;
74
75         return LDAP_SUCCESS;
76 }
77
78 static int
79 rwm_add( Operation *op, SlapReply *rs )
80 {
81         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
82         struct ldaprwmap        *rwmap = 
83                         (struct ldaprwmap *)on->on_bi.bi_private;
84
85         int                     rc,
86                                 i,
87                                 isupdate;
88         Attribute               **ap = NULL;
89
90 #ifdef ENABLE_REWRITE
91         rc = rwm_op_dn_massage( op, rs, "addDn" );
92 #else
93         rc = 1;
94         rc = rwm_op_dn_massage( op, rs, &rc );
95 #endif
96         if ( rc != LDAP_SUCCESS ) {
97                 op->o_bd->bd_info = (BackendInfo *)on->on_info;
98                 send_ldap_error( op, rs, rc, "addDn massage error" );
99                 return -1;
100         }
101
102         /* Count number of attributes in entry */ 
103         isupdate = be_isupdate( op->o_bd, &op->o_ndn );
104         for ( i = 0, ap = &op->oq_add.rs_e->e_attrs; *ap; ) {
105                 struct berval   mapped;
106                 Attribute       *a;
107
108                 if ( !isupdate && (*ap)->a_desc->ad_type->sat_no_user_mod ) {
109                         goto cleanup_attr;
110                 }
111
112                 rwm_map( &rwmap->rwm_at, &(*ap)->a_desc->ad_cname,
113                                 &mapped, RWM_MAP );
114                 if ( mapped.bv_val == NULL || mapped.bv_val[0] == '\0' ) {
115                         goto cleanup_attr;
116                 }
117
118                 if ( (*ap)->a_desc->ad_type->sat_syntax
119                                 == slap_schema.si_syn_distinguishedName )
120                 {
121                         /*
122                          * FIXME: rewrite could fail; in this case
123                          * the operation should give up, right?
124                          */
125 #ifdef ENABLE_REWRITE
126                         rc = rwm_dnattr_rewrite( op, rs, "addDn",
127                                         (*ap)->a_vals );
128 #else
129                         rc = 1;
130                         rc = rwm_dnattr_rewrite( op, rs, &rc,
131                                         (*ap)->a_vals );
132 #endif
133                         if ( rc ) {
134                                 goto cleanup_attr;
135                         }
136                 }
137
138                 ap = &(*ap)->a_next;
139                 continue;
140
141 cleanup_attr:;
142                 /* FIXME: leaking attribute/values? */
143                 a = *ap;
144
145                 *ap = (*ap)->a_next;
146                 ber_bvarray_free( a->a_vals );
147                 ber_bvarray_free( a->a_nvals );
148                 ch_free( a );
149         }
150
151
152         /* TODO: map attribute types, values of DN-valued attributes ... */
153         return SLAP_CB_CONTINUE;
154 }
155
156 static int
157 rwm_bind( Operation *op, SlapReply *rs )
158 {
159         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
160         int                     rc;
161
162 #ifdef ENABLE_REWRITE
163         rc = rwm_op_dn_massage( op, rs, "bindDn" );
164 #else
165         rc = 1;
166         rc = rwm_op_dn_massage( op, rs, &rc );
167 #endif
168         if ( rc != LDAP_SUCCESS ) {
169                 op->o_bd->bd_info = (BackendInfo *)on->on_info;
170                 send_ldap_error( op, rs, rc, "bindDn massage error" );
171                 return -1;
172         }
173
174         return SLAP_CB_CONTINUE;
175 }
176
177 static int
178 rwm_compare( Operation *op, SlapReply *rs )
179 {
180         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
181         struct ldaprwmap        *rwmap = 
182                         (struct ldaprwmap *)on->on_bi.bi_private;
183
184         int                     rc;
185         struct berval           mapped_at = { 0, NULL },
186                                 mapped_vals[2] = { { 0, NULL }, { 0, NULL } };
187
188 #ifdef ENABLE_REWRITE
189         rc = rwm_op_dn_massage( op, rs, "compareDn" );
190 #else
191         rc = 1;
192         rc = rwm_op_dn_massage( op, rs, &rc );
193 #endif
194         if ( rc != LDAP_SUCCESS ) {
195                 op->o_bd->bd_info = (BackendInfo *)on->on_info;
196                 send_ldap_error( op, rs, rc, "compareDn massage error" );
197                 return -1;
198         }
199
200         /* if the attribute is an objectClass, try to remap its value */
201         if ( op->orc_ava->aa_desc == slap_schema.si_ad_objectClass
202                         || op->orc_ava->aa_desc == slap_schema.si_ad_structuralObjectClass )
203         {
204                 rwm_map( &rwmap->rwm_oc, &op->orc_ava->aa_value,
205                                 &mapped_vals[0], RWM_MAP );
206                 if ( mapped_vals[0].bv_val == NULL
207                                 || mapped_vals[0].bv_val[0] == '\0')
208                 {
209                         op->o_bd->bd_info = (BackendInfo *)on->on_info;
210                         send_ldap_error( op, rs, LDAP_OTHER, "compare objectClass map error" );
211                         return -1;
212
213                 } else if ( mapped_vals[0].bv_val != op->orc_ava->aa_value.bv_val ) {
214                         free( op->orc_ava->aa_value.bv_val );
215                         op->orc_ava->aa_value = mapped_vals[0];
216                 }
217                 mapped_at = op->orc_ava->aa_desc->ad_cname;
218
219         } else {
220                 rwm_map( &rwmap->rwm_at,
221                                 &op->orc_ava->aa_desc->ad_cname,
222                                 &mapped_at,
223                                 RWM_MAP );
224                 if ( mapped_at.bv_val == NULL 
225                                 || mapped_at.bv_val[0] == '\0')
226                 {
227                         op->o_bd->bd_info = (BackendInfo *)on->on_info;
228                         send_ldap_error( op, rs, LDAP_OTHER, "compare attributeType map error" );
229                         return -1;
230                 }
231                 if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
232                 {
233                         mapped_vals[0] = op->orc_ava->aa_value;
234                         rc = rwm_dnattr_rewrite( op, rs, "compareAttrDN", mapped_vals );
235                         if ( rc != LDAP_SUCCESS ) {
236                                 op->o_bd->bd_info = (BackendInfo *)on->on_info;
237                                 send_ldap_error( op, rs, rc, "compareAttrDN massage error" );
238                                 return -1;
239                         }
240
241                         if ( mapped_vals[0].bv_val != op->orc_ava->aa_value.bv_val ) {
242                                 free( op->orc_ava->aa_value.bv_val );
243                                 op->orc_ava->aa_value = mapped_vals[0];
244                         }
245                 }
246         }
247
248         /* TODO: rewrite attribute types, values of DN-valued attributes ... */
249         return SLAP_CB_CONTINUE;
250 }
251
252 static int
253 rwm_delete( Operation *op, SlapReply *rs )
254 {
255         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
256         int                     rc;
257
258 #ifdef ENABLE_REWRITE
259         rc = rwm_op_dn_massage( op, rs, "deleteDn" );
260 #else
261         rc = 1;
262         rc = rwm_op_dn_massage( op, rs, &rc );
263 #endif
264         if ( rc != LDAP_SUCCESS ) {
265                 op->o_bd->bd_info = (BackendInfo *)on->on_info;
266                 send_ldap_error( op, rs, rc, "deleteDn massage error" );
267                 return rc;
268         }
269
270         return SLAP_CB_CONTINUE;
271 }
272
273 static int
274 rwm_modify( Operation *op, SlapReply *rs )
275 {
276         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
277         int                     rc;
278
279 #ifdef ENABLE_REWRITE
280         rc = rwm_op_dn_massage( op, rs, "modifyDn" );
281 #else
282         rc = 1;
283         rc = rwm_op_dn_massage( op, rs, &rc );
284 #endif
285         if ( rc != LDAP_SUCCESS ) {
286                 op->o_bd->bd_info = (BackendInfo *)on->on_info;
287                 send_ldap_error( op, rs, rc, "modifyDn massage error" );
288                 return rc;
289         }
290
291         /* TODO: rewrite attribute types, values of DN-valued attributes ... */
292         return SLAP_CB_CONTINUE;
293 }
294
295 static int
296 rwm_modrdn( Operation *op, SlapReply *rs )
297 {
298         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
299         int                     rc;
300
301 #ifdef ENABLE_REWRITE
302         rc = rwm_op_dn_massage( op, rs, "renameDn" );
303 #else
304         rc = 1;
305         rc = rwm_op_dn_massage( op, rs, &rc );
306 #endif
307         if ( rc != LDAP_SUCCESS ) {
308                 op->o_bd->bd_info = (BackendInfo *)on->on_info;
309                 send_ldap_error( op, rs, rc, "renameDn massage error" );
310                 return rc;
311         }
312
313         /* TODO: rewrite attribute types, values of DN-valued attributes ... */
314         return SLAP_CB_CONTINUE;
315 }
316
317 static int
318 rwm_search( Operation *op, SlapReply *rs )
319 {
320         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
321         int                     rc;
322
323 #ifdef ENABLE_REWRITE
324         rc = rwm_op_dn_massage( op, rs, "searchDn" );
325 #else
326         rc = 1;
327         rc = rwm_op_dn_massage( op, rs, &rc );
328 #endif
329         if ( rc != LDAP_SUCCESS ) {
330                 op->o_bd->bd_info = (BackendInfo *)on->on_info;
331                 send_ldap_error( op, rs, rc, "searchDn massage error" );
332                 return rc;
333         }
334
335         /* TODO: rewrite/map filter & attrs */
336         return SLAP_CB_CONTINUE;
337 }
338
339 static int
340 rwm_extended( Operation *op, SlapReply *rs )
341 {
342         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
343         int                     rc;
344
345 #ifdef ENABLE_REWRITE
346         rc = rwm_op_dn_massage( op, rs, "extendedDn" );
347 #else
348         rc = 1;
349         rc = rwm_op_dn_massage( op, rs, &rc );
350 #endif
351         if ( rc != LDAP_SUCCESS ) {
352                 op->o_bd->bd_info = (BackendInfo *)on->on_info;
353                 send_ldap_error( op, rs, rc, "extendedDn massage error" );
354                 return rc;
355         }
356
357         /* TODO: rewrite/map extended data ? ... */
358         return 0;
359 }
360
361 static int
362 rwm_matched( Operation *op, SlapReply *rs )
363 {
364         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
365         struct ldaprwmap        *rwmap = 
366                         (struct ldaprwmap *)on->on_bi.bi_private;
367
368         struct berval           dn, mdn;
369         dncookie                dc;
370
371         if ( rs->sr_matched == NULL ) {
372                 return SLAP_CB_CONTINUE;
373         }
374
375         dc.rwmap = rwmap;
376 #ifdef ENABLE_REWRITE
377         dc.conn = op->o_conn;
378         dc.rs = rs;
379         dc.ctx = "matchedDN";
380 #else
381         dc.tofrom = 0;
382         dc.normalized = 0;
383 #endif
384         ber_str2bv( rs->sr_matched, 0, 0, &dn );
385         rwm_dn_massage( &dc, &dn, &mdn );
386
387         if ( mdn.bv_val != dn.bv_val ) {
388                 if ( rs->sr_flags & REP_MATCHED_MUSTBEFREED ) {
389                         ch_free( (void *)rs->sr_matched );
390                 } else {
391                         rs->sr_flags |= REP_MATCHED_MUSTBEFREED;
392                 }
393                 rs->sr_matched = mdn.bv_val;
394         }
395         
396         return SLAP_CB_CONTINUE;
397 }
398
399 static int
400 rwm_send_entry( Operation *op, SlapReply *rs )
401 {
402         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
403         struct ldaprwmap        *rwmap = 
404                         (struct ldaprwmap *)on->on_bi.bi_private;
405
406         Entry           *e = NULL;
407         struct berval   dn = { 0, NULL }, ndn = { 0, NULL };
408         dncookie        dc;
409         int             rc = SLAP_CB_CONTINUE;
410
411         assert( rs->sr_entry );
412
413         e = rs->sr_entry;
414
415         /*
416          * Rewrite the dn of the result, if needed
417          */
418         dc.rwmap = rwmap;
419 #ifdef ENABLE_REWRITE
420         dc.conn = op->o_conn;
421         dc.rs = NULL; 
422         dc.ctx = "searchResult";
423 #else
424         dc.tofrom = 0;
425         dc.normalized = 0;
426 #endif
427         if ( rwm_dn_massage( &dc, &e->e_name, &dn ) ) {
428                 return LDAP_OTHER;
429         }
430
431         if ( e->e_name.bv_val == dn.bv_val ) {
432                 return SLAP_CB_CONTINUE;
433         }
434
435         /*
436          * Note: this may fail if the target host(s) schema differs
437          * from the one known to the meta, and a DN with unknown
438          * attributes is returned.
439          */
440         if ( dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL ) != LDAP_SUCCESS ) {
441                 if ( dn.bv_val != e->e_name.bv_val ) {
442                         ch_free( dn.bv_val );
443                 }
444                 rc = LDAP_INVALID_DN_SYNTAX;
445                 goto fail;
446         }
447
448         if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE ) ) {
449                 e = entry_dup( e );
450                 if ( e == NULL ) {
451                         goto fail;
452                 }
453                 rs->sr_flags |= ( REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED );
454         }
455
456         free( e->e_name.bv_val );
457         free( e->e_nname.bv_val );
458
459         e->e_name = dn;
460         e->e_nname = ndn;
461
462         rs->sr_entry = e;
463
464         /* TODO: map entry attribute types, objectclasses 
465          * and dn-valued attribute values */
466         
467         return SLAP_CB_CONTINUE;
468
469 fail:;
470         if ( dn.bv_val && ( dn.bv_val != e->e_name.bv_val ) ) {
471                 ch_free( dn.bv_val );
472         }
473
474         if ( ndn.bv_val ) {
475                 ch_free( ndn.bv_val );
476         }
477
478         return rc;
479 }
480
481 static int
482 rwm_rw_config(
483     BackendDB   *be,
484     const char  *fname,
485     int         lineno,
486     int         argc,
487     char        **argv
488 )
489 {
490 #ifdef ENABLE_REWRITE
491         slap_overinst           *on = (slap_overinst *) be->bd_info;
492         struct ldaprwmap        *rwmap = 
493                         (struct ldaprwmap *)on->on_bi.bi_private;
494
495         return rewrite_parse( rwmap->rwm_rw,
496                                 fname, lineno, argc, argv );
497
498 #else /* !ENABLE_REWRITE */
499         fprintf( stderr, "%s: line %d: rewrite capabilities "
500                         "are not enabled\n", fname, lineno );
501 #endif /* !ENABLE_REWRITE */
502                 
503         return 0;
504 }
505
506 static int
507 rwm_suffixmassage_config(
508     BackendDB   *be,
509     const char  *fname,
510     int         lineno,
511     int         argc,
512     char        **argv
513 )
514 {
515         slap_overinst           *on = (slap_overinst *) be->bd_info;
516         struct ldaprwmap        *rwmap = 
517                         (struct ldaprwmap *)on->on_bi.bi_private;
518
519         struct berval   bvnc, nvnc, pvnc, brnc, nrnc, prnc;
520 #ifdef ENABLE_REWRITE
521         int             rc;
522 #endif /* ENABLE_REWRITE */
523                 
524         /*
525          * syntax:
526          * 
527          *      suffixmassage <suffix> <massaged suffix>
528          *
529          * the <suffix> field must be defined as a valid suffix
530          * (or suffixAlias?) for the current database;
531          * the <massaged suffix> shouldn't have already been
532          * defined as a valid suffix or suffixAlias for the 
533          * current server
534          */
535         if ( argc != 3 ) {
536                 fprintf( stderr, "%s: line %d: syntax is"
537                                " \"suffixMassage <suffix>"
538                                " <massaged suffix>\"\n",
539                         fname, lineno );
540                 return 1;
541         }
542                 
543         ber_str2bv( argv[1], 0, 0, &bvnc );
544         if ( dnPrettyNormal( NULL, &bvnc, &pvnc, &nvnc, NULL ) != LDAP_SUCCESS ) {
545                 fprintf( stderr, "%s: line %d: suffix DN %s is invalid\n",
546                         fname, lineno, bvnc.bv_val );
547                 return 1;
548         }
549
550         ber_str2bv( argv[2], 0, 0, &brnc );
551         if ( dnPrettyNormal( NULL, &brnc, &prnc, &nrnc, NULL ) != LDAP_SUCCESS ) {
552                 fprintf( stderr, "%s: line %d: suffix DN %s is invalid\n",
553                                 fname, lineno, brnc.bv_val );
554                 free( nvnc.bv_val );
555                 free( pvnc.bv_val );
556                 return 1;
557         }
558
559 #ifdef ENABLE_REWRITE
560         /*
561          * The suffix massaging is emulated 
562          * by means of the rewrite capabilities
563          */
564         rc = rwm_suffix_massage_config( rwmap->rwm_rw,
565                         &pvnc, &nvnc, &prnc, &nrnc );
566         free( nvnc.bv_val );
567         free( pvnc.bv_val );
568         free( nrnc.bv_val );
569         free( prnc.bv_val );
570
571         return( rc );
572
573 #else /* !ENABLE_REWRITE */
574         ber_bvarray_add( &rwmap->rwm_suffix_massage, &pvnc );
575         ber_bvarray_add( &rwmap->rwm_suffix_massage, &nvnc );
576                 
577         ber_bvarray_add( &rwmap->rwm_suffix_massage, &prnc );
578         ber_bvarray_add( &rwmap->rwm_suffix_massage, &nrnc );
579 #endif /* !ENABLE_REWRITE */
580
581         return 0;
582 }
583
584 static int
585 rwm_m_config(
586     BackendDB   *be,
587     const char  *fname,
588     int         lineno,
589     int         argc,
590     char        **argv
591 )
592 {
593         slap_overinst           *on = (slap_overinst *) be->bd_info;
594         struct ldaprwmap        *rwmap = 
595                         (struct ldaprwmap *)on->on_bi.bi_private;
596
597         /* objectclass/attribute mapping */
598         return rwm_map_config( &rwmap->rwm_oc,
599                         &rwmap->rwm_at,
600                         fname, lineno, argc, argv );
601 }
602
603 static int
604 rwm_response( Operation *op, SlapReply *rs )
605 {
606         int     rc;
607
608         if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH ) {
609                 return rwm_send_entry( op, rs );
610         }
611
612         switch( op->o_tag ) {
613         case LDAP_REQ_BIND:
614         case LDAP_REQ_ADD:
615         case LDAP_REQ_DELETE:
616         case LDAP_REQ_MODRDN:
617         case LDAP_REQ_MODIFY:
618         case LDAP_REQ_COMPARE:
619         case LDAP_REQ_SEARCH:
620         case LDAP_REQ_EXTENDED:
621                 rc = rwm_matched( op, rs );
622                 break;
623         default:
624                 rc = SLAP_CB_CONTINUE;
625                 break;
626         }
627
628         return rc;
629 }
630
631 static int
632 rwm_config(
633     BackendDB   *be,
634     const char  *fname,
635     int         lineno,
636     int         argc,
637     char        **argv
638 )
639 {
640         int             rc = 0;
641
642         if ( strncasecmp( argv[0], "rewrite", sizeof("rewrite") - 1) == 0 ) {
643                 rc = rwm_rw_config( be, fname, lineno, argc, argv );
644
645         } else if (strcasecmp( argv[0], "map" ) == 0 ) {
646                 rc = rwm_m_config( be, fname, lineno, argc, argv );
647
648         } else if (strcasecmp( argv[0], "suffixmassage" ) == 0 ) {
649                 rc = rwm_suffixmassage_config( be, fname, lineno, argc, argv );
650
651         } else {
652                 rc = SLAP_CONF_UNKNOWN;
653         }
654
655         return rc;
656 }
657
658 static int
659 rwm_over_init(
660         BackendDB *be
661 )
662 {
663         slap_overinst           *on = (slap_overinst *) be->bd_info;
664         struct ldapmapping      *mapping = NULL;
665         struct ldaprwmap        *rwmap;
666
667         rwmap = (struct ldaprwmap *)ch_malloc(sizeof(struct ldaprwmap));
668         memset(rwmap, 0, sizeof(struct ldaprwmap));
669
670 #ifdef ENABLE_REWRITE
671         rwmap->rwm_rw = rewrite_info_init( REWRITE_MODE_USE_DEFAULT );
672         if ( rwmap->rwm_rw == NULL ) {
673                 ch_free( rwmap );
674                 return -1;
675         }
676
677         {
678                 char    *rargv[3];
679
680                 /* this rewriteContext by default must be null;
681                  * rules can be added if required */
682                 rargv[ 0 ] = "rewriteContext";
683                 rargv[ 1 ] = "searchFilter";
684                 rargv[ 2 ] = NULL;
685                 rewrite_parse( rwmap->rwm_rw, "<suffix massage>", 1, 2, rargv );
686
687                 rargv[ 0 ] = "rewriteContext";
688                 rargv[ 1 ] = "default";
689                 rargv[ 2 ] = NULL;
690                 rewrite_parse( rwmap->rwm_rw, "<suffix massage>", 2, 2, rargv );
691         }
692         
693 #endif /* ENABLE_REWRITE */
694
695         rwm_map_init( &rwmap->rwm_oc, &mapping );
696         rwm_map_init( &rwmap->rwm_at, &mapping );
697
698         on->on_bi.bi_private = (void *)rwmap;
699
700         return 0;
701 }
702
703 static int
704 rwm_destroy(
705         BackendDB *be
706 )
707 {
708         slap_overinst   *on = (slap_overinst *) be->bd_info;
709         int             rc = 0;
710
711         if ( on->on_bi.bi_private ) {
712                 struct ldaprwmap        *rwmap = 
713                         (struct ldaprwmap *)on->on_bi.bi_private;
714
715 #ifdef ENABLE_REWRITE
716                 if (rwmap->rwm_rw) {
717                         rewrite_info_delete( &rwmap->rwm_rw );
718                 }
719 #else /* !ENABLE_REWRITE */
720                 if ( rwmap->rwm_suffix_massage ) {
721                         ber_bvarray_free( rwmap->rwm_suffix_massage );
722                 }
723 #endif /* !ENABLE_REWRITE */
724
725                 avl_free( rwmap->rwm_oc.remap, NULL );
726                 avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
727                 avl_free( rwmap->rwm_at.remap, NULL );
728                 avl_free( rwmap->rwm_at.map, rwm_mapping_free );
729         }
730
731         return rc;
732 }
733
734 static slap_overinst rwm = { { NULL } };
735
736 int
737 rwm_init(void)
738 {
739         memset( &rwm, 0, sizeof(slap_overinst) );
740
741         rwm.on_bi.bi_type = "rewrite-remap";
742         rwm.on_bi.bi_db_init = rwm_over_init;
743         rwm.on_bi.bi_db_config = rwm_config;
744         rwm.on_bi.bi_db_destroy = rwm_destroy;
745
746         rwm.on_bi.bi_op_bind = rwm_bind;
747         rwm.on_bi.bi_op_search = rwm_search;
748         rwm.on_bi.bi_op_compare = rwm_compare;
749         rwm.on_bi.bi_op_modify = rwm_modify;
750         rwm.on_bi.bi_op_modrdn = rwm_modrdn;
751         rwm.on_bi.bi_op_add = rwm_add;
752         rwm.on_bi.bi_op_delete = rwm_delete;
753         rwm.on_bi.bi_extended = rwm_extended;
754
755         rwm.on_response = rwm_response;
756
757         return overlay_register( &rwm );
758 }
759
760 #if SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC
761 int init_module(int argc, char *argv[]) {
762         return rwm_init();
763 }
764 #endif
765
766 #endif /* SLAPD_OVER_RWM */