Back to index

openldap  2.4.31
rwmmap.c
Go to the documentation of this file.
00001 /* rwmmap.c - rewrite/mapping routines */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 1999-2012 The OpenLDAP Foundation.
00006  * Portions Copyright 1999-2003 Howard Chu.
00007  * Portions Copyright 2000-2003 Pierangelo Masarati.
00008  * All rights reserved.
00009  *
00010  * Redistribution and use in source and binary forms, with or without
00011  * modification, are permitted only as authorized by the OpenLDAP
00012  * Public License.
00013  *
00014  * A copy of this license is available in the file LICENSE in the
00015  * top-level directory of the distribution or, alternatively, at
00016  * <http://www.OpenLDAP.org/license.html>.
00017  */
00018 /* ACKNOWLEDGEMENTS:
00019  * This work was initially developed by the Howard Chu for inclusion
00020  * in OpenLDAP Software and subsequently enhanced by Pierangelo
00021  * Masarati.
00022  */
00023 
00024 #include "portable.h"
00025 
00026 #ifdef SLAPD_OVER_RWM
00027 
00028 #include <stdio.h>
00029 
00030 #include <ac/string.h>
00031 #include <ac/socket.h>
00032 
00033 #include "slap.h"
00034 #include "rwm.h"
00035 
00036 #undef ldap_debug    /* silence a warning in ldap-int.h */
00037 #include "../../../libraries/libldap/ldap-int.h"
00038 
00039 int
00040 rwm_mapping_cmp( const void *c1, const void *c2 )
00041 {
00042        struct ldapmapping *map1 = (struct ldapmapping *)c1;
00043        struct ldapmapping *map2 = (struct ldapmapping *)c2;
00044        int rc = map1->m_src.bv_len - map2->m_src.bv_len;
00045        
00046        if ( rc ) {
00047               return rc;
00048        }
00049 
00050        return strcasecmp( map1->m_src.bv_val, map2->m_src.bv_val );
00051 }
00052 
00053 int
00054 rwm_mapping_dup( void *c1, void *c2 )
00055 {
00056        struct ldapmapping *map1 = (struct ldapmapping *)c1;
00057        struct ldapmapping *map2 = (struct ldapmapping *)c2;
00058        int rc = map1->m_src.bv_len - map2->m_src.bv_len;
00059 
00060        if ( rc ) {
00061               return 0;
00062        }
00063 
00064        return ( ( strcasecmp( map1->m_src.bv_val, map2->m_src.bv_val ) == 0 ) ? -1 : 0 );
00065 }
00066 
00067 int
00068 rwm_map_init( struct ldapmap *lm, struct ldapmapping **m )
00069 {
00070        struct ldapmapping   *mapping;
00071        const char           *text;
00072        int                  rc;
00073 
00074        assert( m != NULL );
00075 
00076        *m = NULL;
00077        
00078        mapping = (struct ldapmapping *)ch_calloc( 2, 
00079                      sizeof( struct ldapmapping ) );
00080        if ( mapping == NULL ) {
00081               return LDAP_NO_MEMORY;
00082        }
00083 
00084        /* NOTE: this is needed to make sure that
00085         *     rwm-map attribute *
00086         * does not  filter out all attributes including objectClass */
00087        rc = slap_str2ad( "objectClass", &mapping[0].m_src_ad, &text );
00088        if ( rc != LDAP_SUCCESS ) {
00089               ch_free( mapping );
00090               return rc;
00091        }
00092 
00093        mapping[0].m_dst_ad = mapping[0].m_src_ad;
00094        ber_dupbv( &mapping[0].m_src, &mapping[0].m_src_ad->ad_cname );
00095        ber_dupbv( &mapping[0].m_dst, &mapping[0].m_src );
00096 
00097        mapping[1].m_src = mapping[0].m_src;
00098        mapping[1].m_dst = mapping[0].m_dst;
00099        mapping[1].m_src_ad = mapping[0].m_src_ad;
00100        mapping[1].m_dst_ad = mapping[1].m_src_ad;
00101 
00102        avl_insert( &lm->map, (caddr_t)&mapping[0], 
00103                      rwm_mapping_cmp, rwm_mapping_dup );
00104        avl_insert( &lm->remap, (caddr_t)&mapping[1], 
00105                      rwm_mapping_cmp, rwm_mapping_dup );
00106 
00107        *m = mapping;
00108 
00109        return rc;
00110 }
00111 
00112 int
00113 rwm_mapping( struct ldapmap *map, struct berval *s, struct ldapmapping **m, int remap )
00114 {
00115        Avlnode *tree;
00116        struct ldapmapping fmapping;
00117 
00118        if ( map == NULL ) {
00119               return 0;
00120        }
00121 
00122        assert( m != NULL );
00123 
00124        /* let special attrnames slip through (ITS#5760) */
00125        if ( bvmatch( s, slap_bv_no_attrs )
00126               || bvmatch( s, slap_bv_all_user_attrs )
00127               || bvmatch( s, slap_bv_all_operational_attrs ) )
00128        {
00129               *m = NULL;
00130               return 0;
00131        }
00132 
00133        if ( remap == RWM_REMAP ) {
00134               tree = map->remap;
00135 
00136        } else {
00137               tree = map->map;
00138        }
00139 
00140        fmapping.m_src = *s;
00141        *m = (struct ldapmapping *)avl_find( tree, (caddr_t)&fmapping,
00142                      rwm_mapping_cmp );
00143 
00144        if ( *m == NULL ) {
00145               return map->drop_missing;
00146        }
00147 
00148        return 0;
00149 }
00150 
00151 void
00152 rwm_map( struct ldapmap *map, struct berval *s, struct berval *bv, int remap )
00153 {
00154        struct ldapmapping *mapping;
00155 
00156        /* map->map may be NULL when mapping is configured,
00157         * but map->remap can't */
00158        if ( map->remap == NULL ) {
00159               *bv = *s;
00160               return;
00161        }
00162 
00163        BER_BVZERO( bv );
00164        ( void )rwm_mapping( map, s, &mapping, remap );
00165        if ( mapping != NULL ) {
00166               if ( !BER_BVISNULL( &mapping->m_dst ) ) {
00167                      *bv = mapping->m_dst;
00168               }
00169               return;
00170        }
00171 
00172        if ( !map->drop_missing ) {
00173               *bv = *s;
00174        }
00175 }
00176 
00177 /*
00178  * Map attribute names in place
00179  */
00180 int
00181 rwm_map_attrnames(
00182        Operation     *op,
00183        struct ldapmap       *at_map,
00184        struct ldapmap       *oc_map,
00185        AttributeName *an,
00186        AttributeName **anp,
00187        int           remap )
00188 {
00189        int           i, j, x;
00190 
00191        assert( anp != NULL );
00192 
00193        *anp = NULL;
00194 
00195        if ( an == NULL && op->o_bd->be_extra_anlist == NULL ) {
00196               return LDAP_SUCCESS;
00197        }
00198 
00199        i = 0;
00200        if ( an != NULL ) {
00201               for ( i = 0; !BER_BVISNULL( &an[i].an_name ); i++ )
00202                      /* just count */ ;
00203        }
00204 
00205        x = 0;
00206        if ( op->o_bd->be_extra_anlist ) {
00207               for ( ; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++ )
00208                      /* just count */ ;
00209        }
00210 
00211        assert( i > 0 || x > 0 );
00212        *anp = op->o_tmpcalloc( ( i + x + 1 ), sizeof( AttributeName ),
00213               op->o_tmpmemctx );
00214        if ( *anp == NULL ) {
00215               return LDAP_NO_MEMORY;
00216        }
00217 
00218        for ( i = 0, j = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) {
00219               struct ldapmapping   *m;
00220               int                  at_drop_missing = 0,
00221                                    oc_drop_missing = 0;
00222 
00223               if ( an[i].an_desc ) {
00224                      if ( !at_map ) {
00225                             /* FIXME: better leave as is? */
00226                             continue;
00227                      }
00228                             
00229                      at_drop_missing = rwm_mapping( at_map, &an[i].an_name, &m, remap );
00230                      if ( at_drop_missing || ( m && BER_BVISNULL( &m->m_dst ) ) ) {
00231                             continue;
00232                      }
00233 
00234                      if ( !m ) {
00235                             (*anp)[j] = an[i];
00236                             j++;
00237                             continue;
00238                      }
00239 
00240                      (*anp)[j] = an[i];
00241                      if ( remap == RWM_MAP ) {
00242                             (*anp)[j].an_name = m->m_dst;
00243                             (*anp)[j].an_desc = m->m_dst_ad;
00244                      } else {
00245                             (*anp)[j].an_name = m->m_src;
00246                             (*anp)[j].an_desc = m->m_src_ad;
00247 
00248                      }
00249 
00250                      j++;
00251                      continue;
00252 
00253               } else if ( an[i].an_oc ) {
00254                      if ( !oc_map ) {
00255                             /* FIXME: better leave as is? */
00256                             continue;
00257                      }
00258 
00259                      oc_drop_missing = rwm_mapping( oc_map, &an[i].an_name, &m, remap );
00260 
00261                      if ( oc_drop_missing || ( m && BER_BVISNULL( &m->m_dst ) ) ) {
00262                             continue;
00263                      }
00264 
00265                      if ( !m ) {
00266                             (*anp)[j] = an[i];
00267                             j++;
00268                             continue;
00269                      }
00270 
00271                      (*anp)[j] = an[i];
00272                      if ( remap == RWM_MAP ) {
00273                             (*anp)[j].an_name = m->m_dst;
00274                             (*anp)[j].an_oc = m->m_dst_oc;
00275                      } else {
00276                             (*anp)[j].an_name = m->m_src;
00277                             (*anp)[j].an_oc = m->m_src_oc;
00278                      }
00279 
00280               } else {
00281                      at_drop_missing = rwm_mapping( at_map, &an[i].an_name, &m, remap );
00282               
00283                      if ( at_drop_missing || !m ) {
00284                             oc_drop_missing = rwm_mapping( oc_map, &an[i].an_name, &m, remap );
00285 
00286                             /* if both at_map and oc_map required to drop missing,
00287                              * then do it */
00288                             if ( oc_drop_missing && at_drop_missing ) {
00289                                    continue;
00290                             }
00291 
00292                             /* if no oc_map mapping was found and at_map required
00293                              * to drop missing, then do it; otherwise, at_map wins
00294                              * and an is considered an attr and is left unchanged */
00295                             if ( !m ) {
00296                                    if ( at_drop_missing ) {
00297                                           continue;
00298                                    }
00299                                    (*anp)[j] = an[i];
00300                                    j++;
00301                                    continue;
00302                             }
00303        
00304                             if ( BER_BVISNULL( &m->m_dst ) ) {
00305                                    continue;
00306                             }
00307 
00308                             (*anp)[j] = an[i];
00309                             if ( remap == RWM_MAP ) {
00310                                    (*anp)[j].an_name = m->m_dst;
00311                                    (*anp)[j].an_oc = m->m_dst_oc;
00312                             } else {
00313                                    (*anp)[j].an_name = m->m_src;
00314                                    (*anp)[j].an_oc = m->m_src_oc;
00315                             }
00316                             j++;
00317                             continue;
00318                      }
00319 
00320                      if ( !BER_BVISNULL( &m->m_dst ) ) {
00321                             (*anp)[j] = an[i];
00322                             if ( remap == RWM_MAP ) {
00323                                    (*anp)[j].an_name = m->m_dst;
00324                                    (*anp)[j].an_desc = m->m_dst_ad;
00325                             } else {
00326                                    (*anp)[j].an_name = m->m_src;
00327                                    (*anp)[j].an_desc = m->m_src_ad;
00328                             }
00329                             j++;
00330                             continue;
00331                      }
00332               }
00333        }
00334 
00335        if ( op->o_bd->be_extra_anlist != NULL ) {
00336               /* we assume be_extra_anlist are already mapped */
00337               for ( x = 0; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++ ) {
00338                      BER_BVZERO( &(*anp)[j].an_name );
00339                      if ( op->o_bd->be_extra_anlist[x].an_desc &&
00340                             ad_inlist( op->o_bd->be_extra_anlist[x].an_desc, *anp ) )
00341                      {
00342                             continue;
00343                      }
00344 
00345                      (*anp)[j] = op->o_bd->be_extra_anlist[x];
00346                      j++;
00347               }
00348        }
00349 
00350        if ( j == 0 && ( i != 0 || x != 0 ) ) {
00351               memset( &(*anp)[0], 0, sizeof( AttributeName ) );
00352               (*anp)[0].an_name = *slap_bv_no_attrs;
00353               j = 1;
00354        }
00355        memset( &(*anp)[j], 0, sizeof( AttributeName ) );
00356 
00357        return LDAP_SUCCESS;
00358 }
00359 
00360 #if 0 /* unused! */
00361 int
00362 rwm_map_attrs(
00363        struct ldapmap       *at_map,
00364        AttributeName *an,
00365        int           remap,
00366        char          ***mapped_attrs )
00367 {
00368        int i, j;
00369        char **na;
00370 
00371        if ( an == NULL ) {
00372               *mapped_attrs = NULL;
00373               return LDAP_SUCCESS;
00374        }
00375 
00376        for ( i = 0; !BER_BVISNULL( &an[ i ].an_name ); i++ )
00377               /* count'em */ ;
00378 
00379        na = (char **)ch_calloc( i + 1, sizeof( char * ) );
00380        if ( na == NULL ) {
00381               *mapped_attrs = NULL;
00382               return LDAP_NO_MEMORY;
00383        }
00384 
00385        for ( i = j = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) {
00386               struct ldapmapping   *mapping;
00387               
00388               if ( rwm_mapping( at_map, &an[i].an_name, &mapping, remap ) ) {
00389                      continue;
00390               }
00391 
00392               if ( !mapping ) {
00393                      na[ j++ ] = an[ i ].an_name.bv_val;
00394                      
00395               } else if ( !BER_BVISNULL( &mapping->m_dst ) ) {
00396                      na[ j++ ] = mapping->m_dst.bv_val;
00397               }
00398        }
00399 
00400        if ( j == 0 && i != 0 ) {
00401               na[ j++ ] = LDAP_NO_ATTRS;
00402        }
00403 
00404        na[ j ] = NULL;
00405 
00406        *mapped_attrs = na;
00407 
00408        return LDAP_SUCCESS;
00409 }
00410 #endif
00411 
00412 static int
00413 map_attr_value(
00414        dncookie             *dc,
00415        AttributeDescription        **adp,
00416        struct berval        *mapped_attr,
00417        struct berval        *value,
00418        struct berval        *mapped_value,
00419        int                  remap,
00420        void                 *memctx )
00421 {
00422        struct berval        vtmp = BER_BVNULL;
00423        int                  freeval = 0;
00424        AttributeDescription *ad = *adp;
00425        struct ldapmapping   *mapping = NULL;
00426 
00427        rwm_mapping( &dc->rwmap->rwm_at, &ad->ad_cname, &mapping, remap );
00428        if ( mapping == NULL ) {
00429               if ( dc->rwmap->rwm_at.drop_missing ) {
00430                      return -1;
00431               }
00432 
00433               *mapped_attr = ad->ad_cname;
00434 
00435        } else {
00436               *mapped_attr = mapping->m_dst;
00437        }
00438 
00439        if ( value != NULL ) {
00440               assert( mapped_value != NULL );
00441 
00442               if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
00443                             || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
00444               {
00445                      dncookie      fdc = *dc;
00446                      int           rc;
00447 
00448                      fdc.ctx = "searchFilterAttrDN";
00449 
00450                      vtmp = *value;
00451                      rc = rwm_dn_massage_normalize( &fdc, value, &vtmp );
00452                      switch ( rc ) {
00453                      case LDAP_SUCCESS:
00454                             if ( vtmp.bv_val != value->bv_val ) {
00455                                    freeval = 1;
00456                             }
00457                             break;
00458               
00459                      case LDAP_UNWILLING_TO_PERFORM:
00460                      case LDAP_OTHER:
00461                      default:
00462                             return -1;
00463                      }
00464 
00465               } else if ( ad->ad_type->sat_equality &&
00466                      ( ad->ad_type->sat_equality->smr_usage & SLAP_MR_MUTATION_NORMALIZER ) )
00467               {
00468                      if ( ad->ad_type->sat_equality->smr_normalize(
00469                             (SLAP_MR_DENORMALIZE|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX),
00470                             NULL, NULL, value, &vtmp, memctx ) )
00471                      {
00472                             return -1;
00473                      }
00474                      freeval = 2;
00475 
00476               } else if ( ad == slap_schema.si_ad_objectClass
00477                             || ad == slap_schema.si_ad_structuralObjectClass )
00478               {
00479                      rwm_map( &dc->rwmap->rwm_oc, value, &vtmp, remap );
00480                      if ( BER_BVISNULL( &vtmp ) || BER_BVISEMPTY( &vtmp ) ) {
00481                             vtmp = *value;
00482                      }
00483               
00484               } else {
00485                      vtmp = *value;
00486               }
00487 
00488               filter_escape_value_x( &vtmp, mapped_value, memctx );
00489 
00490               switch ( freeval ) {
00491               case 1:
00492                      ch_free( vtmp.bv_val );
00493                      break;
00494 
00495               case 2:
00496                      ber_memfree_x( vtmp.bv_val, memctx );
00497                      break;
00498               }
00499        }
00500        
00501        if ( mapping != NULL ) {
00502               assert( mapping->m_dst_ad != NULL );
00503               *adp = mapping->m_dst_ad;
00504        }
00505 
00506        return 0;
00507 }
00508 
00509 static int
00510 rwm_int_filter_map_rewrite(
00511        Operation            *op,
00512        dncookie             *dc,
00513        Filter               *f,
00514        struct berval        *fstr )
00515 {
00516        int           i;
00517        Filter        *p;
00518        AttributeDescription *ad;
00519        struct berval atmp,
00520                      vtmp,
00521                      *tmp;
00522        static struct berval
00523                      /* better than nothing... */
00524                      ber_bvfalse = BER_BVC( "(!(objectClass=*))" ),
00525                      ber_bvtf_false = BER_BVC( "(|)" ),
00526                      /* better than nothing... */
00527                      ber_bvtrue = BER_BVC( "(objectClass=*)" ),
00528                      ber_bvtf_true = BER_BVC( "(&)" ),
00529 #if 0
00530                      /* no longer needed; preserved for completeness */
00531                      ber_bvundefined = BER_BVC( "(?=undefined)" ),
00532 #endif
00533                      ber_bverror = BER_BVC( "(?=error)" ),
00534                      ber_bvunknown = BER_BVC( "(?=unknown)" ),
00535                      ber_bvnone = BER_BVC( "(?=none)" );
00536        ber_len_t     len;
00537 
00538        assert( fstr != NULL );
00539        BER_BVZERO( fstr );
00540 
00541        if ( f == NULL ) {
00542               ber_dupbv_x( fstr, &ber_bvnone, op->o_tmpmemctx );
00543               return LDAP_OTHER;
00544        }
00545 
00546 #if 0
00547        /* ITS#6814: give the caller a chance to use undefined filters */
00548        if ( f->f_choice & SLAPD_FILTER_UNDEFINED ) {
00549               goto computed;
00550        }
00551 #endif
00552 
00553        switch ( f->f_choice & SLAPD_FILTER_MASK ) {
00554        case LDAP_FILTER_EQUALITY:
00555               ad = f->f_av_desc;
00556               if ( map_attr_value( dc, &ad, &atmp,
00557                      &f->f_av_value, &vtmp, RWM_MAP, op->o_tmpmemctx ) )
00558               {
00559                      goto computed;
00560               }
00561 
00562               fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(=)" );
00563               fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
00564 
00565               snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
00566                      atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
00567 
00568               op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
00569               break;
00570 
00571        case LDAP_FILTER_GE:
00572               ad = f->f_av_desc;
00573               if ( map_attr_value( dc, &ad, &atmp,
00574                      &f->f_av_value, &vtmp, RWM_MAP, op->o_tmpmemctx ) )
00575               {
00576                      goto computed;
00577               }
00578 
00579               fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(>=)" );
00580               fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
00581 
00582               snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
00583                      atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
00584 
00585               op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
00586               break;
00587 
00588        case LDAP_FILTER_LE:
00589               ad = f->f_av_desc;
00590               if ( map_attr_value( dc, &ad, &atmp,
00591                      &f->f_av_value, &vtmp, RWM_MAP, op->o_tmpmemctx ) )
00592               {
00593                      goto computed;
00594               }
00595 
00596               fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(<=)" );
00597               fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
00598 
00599               snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
00600                      atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
00601 
00602               op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
00603               break;
00604 
00605        case LDAP_FILTER_APPROX:
00606               ad = f->f_av_desc;
00607               if ( map_attr_value( dc, &ad, &atmp,
00608                      &f->f_av_value, &vtmp, RWM_MAP, op->o_tmpmemctx ) )
00609               {
00610                      goto computed;
00611               }
00612 
00613               fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(~=)" );
00614               fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
00615 
00616               snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
00617                      atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
00618 
00619               op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
00620               break;
00621 
00622        case LDAP_FILTER_SUBSTRINGS:
00623               ad = f->f_sub_desc;
00624               if ( map_attr_value( dc, &ad, &atmp,
00625                      NULL, NULL, RWM_MAP, op->o_tmpmemctx ) )
00626               {
00627                      goto computed;
00628               }
00629 
00630               /* cannot be a DN ... */
00631 
00632               fstr->bv_len = atmp.bv_len + STRLENOF( "(=*)" );
00633               fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 128, op->o_tmpmemctx );
00634 
00635               snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
00636                      atmp.bv_val );
00637 
00638               if ( !BER_BVISNULL( &f->f_sub_initial ) ) {
00639                      len = fstr->bv_len;
00640 
00641                      filter_escape_value_x( &f->f_sub_initial, &vtmp, op->o_tmpmemctx );
00642 
00643                      fstr->bv_len += vtmp.bv_len;
00644                      fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1,
00645                             op->o_tmpmemctx );
00646 
00647                      snprintf( &fstr->bv_val[len - 2], vtmp.bv_len + 3,
00648                             /* "(attr=" */ "%s*)",
00649                             vtmp.bv_len ? vtmp.bv_val : "" );
00650 
00651                      op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
00652               }
00653 
00654               if ( f->f_sub_any != NULL ) {
00655                      for ( i = 0; !BER_BVISNULL( &f->f_sub_any[i] ); i++ ) {
00656                             len = fstr->bv_len;
00657                             filter_escape_value_x( &f->f_sub_any[i], &vtmp,
00658                                    op->o_tmpmemctx );
00659 
00660                             fstr->bv_len += vtmp.bv_len + 1;
00661                             fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1,
00662                                    op->o_tmpmemctx );
00663 
00664                             snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
00665                                    /* "(attr=[init]*[any*]" */ "%s*)",
00666                                    vtmp.bv_len ? vtmp.bv_val : "" );
00667                             op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
00668                      }
00669               }
00670 
00671               if ( !BER_BVISNULL( &f->f_sub_final ) ) {
00672                      len = fstr->bv_len;
00673 
00674                      filter_escape_value_x( &f->f_sub_final, &vtmp, op->o_tmpmemctx );
00675 
00676                      fstr->bv_len += vtmp.bv_len;
00677                      fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1,
00678                             op->o_tmpmemctx );
00679 
00680                      snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
00681                             /* "(attr=[init*][any*]" */ "%s)",
00682                             vtmp.bv_len ? vtmp.bv_val : "" );
00683 
00684                      op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
00685               }
00686 
00687               break;
00688 
00689        case LDAP_FILTER_PRESENT:
00690               ad = f->f_desc;
00691               if ( map_attr_value( dc, &ad, &atmp,
00692                      NULL, NULL, RWM_MAP, op->o_tmpmemctx ) )
00693               {
00694                      goto computed;
00695               }
00696 
00697               fstr->bv_len = atmp.bv_len + STRLENOF( "(=*)" );
00698               fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
00699 
00700               snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
00701                      atmp.bv_val );
00702               break;
00703 
00704        case LDAP_FILTER_AND:
00705        case LDAP_FILTER_OR:
00706        case LDAP_FILTER_NOT:
00707               fstr->bv_len = STRLENOF( "(%)" );
00708               fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 128, op->o_tmpmemctx );
00709 
00710               snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)",
00711                      f->f_choice == LDAP_FILTER_AND ? '&' :
00712                      f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
00713 
00714               for ( p = f->f_list; p != NULL; p = p->f_next ) {
00715                      int    rc;
00716 
00717                      len = fstr->bv_len;
00718 
00719                      rc = rwm_int_filter_map_rewrite( op, dc, p, &vtmp );
00720                      if ( rc != LDAP_SUCCESS ) {
00721                             return rc;
00722                      }
00723                      
00724                      fstr->bv_len += vtmp.bv_len;
00725                      fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1,
00726                             op->o_tmpmemctx );
00727 
00728                      snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2, 
00729                             /*"("*/ "%s)", vtmp.bv_len ? vtmp.bv_val : "" );
00730 
00731                      op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
00732               }
00733 
00734               break;
00735 
00736        case LDAP_FILTER_EXT: {
00737               if ( f->f_mr_desc ) {
00738                      ad = f->f_mr_desc;
00739                      if ( map_attr_value( dc, &ad, &atmp,
00740                             &f->f_mr_value, &vtmp, RWM_MAP, op->o_tmpmemctx ) )
00741                      {
00742                             goto computed;
00743                      }
00744 
00745               } else {
00746                      BER_BVSTR( &atmp, "" );
00747                      filter_escape_value_x( &f->f_mr_value, &vtmp, op->o_tmpmemctx );
00748               }
00749                      
00750 
00751               fstr->bv_len = atmp.bv_len +
00752                      ( f->f_mr_dnattrs ? STRLENOF( ":dn" ) : 0 ) +
00753                      ( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len + 1 : 0 ) +
00754                      vtmp.bv_len + STRLENOF( "(:=)" );
00755               fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
00756 
00757               snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
00758                      atmp.bv_val,
00759                      f->f_mr_dnattrs ? ":dn" : "",
00760                      !BER_BVISEMPTY( &f->f_mr_rule_text ) ? ":" : "",
00761                      !BER_BVISEMPTY( &f->f_mr_rule_text ) ? f->f_mr_rule_text.bv_val : "",
00762                      vtmp.bv_len ? vtmp.bv_val : "" );
00763               op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
00764               break;
00765        }
00766 
00767        case -1:
00768 computed:;
00769               filter_free_x( op, f, 0 );
00770               f->f_choice = SLAPD_FILTER_COMPUTED;
00771               f->f_result = SLAPD_COMPARE_UNDEFINED;
00772               /* fallthru */
00773 
00774        case SLAPD_FILTER_COMPUTED:
00775               switch ( f->f_result ) {
00776               case LDAP_COMPARE_FALSE:
00777               /* FIXME: treat UNDEFINED as FALSE */
00778               case SLAPD_COMPARE_UNDEFINED:
00779                      if ( dc->rwmap->rwm_flags & RWM_F_SUPPORT_T_F ) {
00780                             tmp = &ber_bvtf_false;
00781                             break;
00782                      }
00783                      tmp = &ber_bvfalse;
00784                      break;
00785 
00786               case LDAP_COMPARE_TRUE:
00787                      if ( dc->rwmap->rwm_flags & RWM_F_SUPPORT_T_F ) {
00788                             tmp = &ber_bvtf_true;
00789                             break;
00790                      }
00791                      tmp = &ber_bvtrue;
00792                      break;
00793                      
00794               default:
00795                      tmp = &ber_bverror;
00796                      break;
00797               }
00798 
00799               ber_dupbv_x( fstr, tmp, op->o_tmpmemctx );
00800               break;
00801               
00802        default:
00803               ber_dupbv_x( fstr, &ber_bvunknown, op->o_tmpmemctx );
00804               break;
00805        }
00806 
00807        return LDAP_SUCCESS;
00808 }
00809 
00810 int
00811 rwm_filter_map_rewrite(
00812        Operation            *op,
00813        dncookie             *dc,
00814        Filter               *f,
00815        struct berval        *fstr )
00816 {
00817        int           rc;
00818        dncookie      fdc;
00819        struct berval ftmp;
00820 
00821        rc = rwm_int_filter_map_rewrite( op, dc, f, fstr );
00822 
00823        if ( rc != 0 ) {
00824               return rc;
00825        }
00826 
00827        fdc = *dc;
00828        ftmp = *fstr;
00829 
00830        fdc.ctx = "searchFilter";
00831 
00832        switch ( rewrite_session( fdc.rwmap->rwm_rw, fdc.ctx, 
00833                             ( !BER_BVISEMPTY( &ftmp ) ? ftmp.bv_val : "" ), 
00834                             fdc.conn, &fstr->bv_val ) )
00835        {
00836        case REWRITE_REGEXEC_OK:
00837               if ( !BER_BVISNULL( fstr ) ) {
00838                      fstr->bv_len = strlen( fstr->bv_val );
00839 
00840               } else {
00841                      *fstr = ftmp;
00842               }
00843 
00844               Debug( LDAP_DEBUG_ARGS,
00845                      "[rw] %s: \"%s\" -> \"%s\"\n",
00846                      fdc.ctx, ftmp.bv_val, fstr->bv_val );            
00847               if ( fstr->bv_val != ftmp.bv_val ) {
00848                      ber_bvreplace_x( &ftmp, fstr, op->o_tmpmemctx );
00849                      ch_free( fstr->bv_val );
00850                      *fstr = ftmp;
00851               }
00852               rc = LDAP_SUCCESS;
00853               break;
00854               
00855        case REWRITE_REGEXEC_UNWILLING:
00856               if ( fdc.rs ) {
00857                      fdc.rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
00858                      fdc.rs->sr_text = "Operation not allowed";
00859               }
00860               op->o_tmpfree( ftmp.bv_val, op->o_tmpmemctx );
00861               rc = LDAP_UNWILLING_TO_PERFORM;
00862               break;
00863                      
00864        case REWRITE_REGEXEC_ERR:
00865               if ( fdc.rs ) {
00866                      fdc.rs->sr_err = LDAP_OTHER;
00867                      fdc.rs->sr_text = "Rewrite error";
00868               }
00869               op->o_tmpfree( ftmp.bv_val, op->o_tmpmemctx );
00870               rc = LDAP_OTHER;
00871               break;
00872        }
00873 
00874        return rc;
00875 }
00876 
00877 /*
00878  * I don't like this much, but we need two different
00879  * functions because different heap managers may be
00880  * in use in back-ldap/meta to reduce the amount of
00881  * calls to malloc routines, and some of the free()
00882  * routines may be macros with args
00883  */
00884 int
00885 rwm_referral_rewrite(
00886        Operation            *op,
00887        SlapReply            *rs,
00888        void                 *cookie,
00889        BerVarray            a_vals,
00890        BerVarray            *pa_nvals )
00891 {
00892        slap_overinst        *on = (slap_overinst *) op->o_bd->bd_info;
00893        struct ldaprwmap     *rwmap = 
00894                      (struct ldaprwmap *)on->on_bi.bi_private;
00895 
00896        int                  i, last;
00897 
00898        dncookie             dc;
00899        struct berval        dn = BER_BVNULL,
00900                             ndn = BER_BVNULL;
00901 
00902        assert( a_vals != NULL );
00903 
00904        /*
00905         * Rewrite the dn if needed
00906         */
00907        dc.rwmap = rwmap;
00908        dc.conn = op->o_conn;
00909        dc.rs = rs;
00910        dc.ctx = (char *)cookie;
00911 
00912        for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ )
00913               ;
00914        last--;
00915        
00916        if ( pa_nvals != NULL ) {
00917               if ( *pa_nvals == NULL ) {
00918                      *pa_nvals = ch_malloc( ( last + 2 ) * sizeof(struct berval) );
00919                      memset( *pa_nvals, 0, ( last + 2 ) * sizeof(struct berval) );
00920               }
00921        }
00922 
00923        for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) {
00924               struct berval olddn = BER_BVNULL,
00925                             oldval;
00926               int           rc;
00927               LDAPURLDesc   *ludp;
00928 
00929               oldval = a_vals[i];
00930               rc = ldap_url_parse( oldval.bv_val, &ludp );
00931               if ( rc != LDAP_URL_SUCCESS ) {
00932                      /* leave attr untouched if massage failed */
00933                      if ( pa_nvals && BER_BVISNULL( &(*pa_nvals)[i] ) ) {
00934                             ber_dupbv( &(*pa_nvals)[i], &oldval );
00935                      }
00936                      continue;
00937               }
00938 
00939               /* FIXME: URLs like "ldap:///dc=suffix" if passed
00940                * thru ldap_url_parse() and ldap_url_desc2str() 
00941                * get rewritten as "ldap:///dc=suffix??base";
00942                * we don't want this to occur... */
00943               if ( ludp->lud_scope == LDAP_SCOPE_BASE ) {
00944                      ludp->lud_scope = LDAP_SCOPE_DEFAULT;
00945               }
00946 
00947               ber_str2bv( ludp->lud_dn, 0, 0, &olddn );
00948 
00949               dn = olddn;
00950               if ( pa_nvals ) {
00951                      ndn = olddn;
00952                      rc = rwm_dn_massage_pretty_normalize( &dc, &olddn,
00953                                    &dn, &ndn );
00954               } else {
00955                      rc = rwm_dn_massage_pretty( &dc, &olddn, &dn );
00956               }
00957 
00958               switch ( rc ) {
00959               case LDAP_UNWILLING_TO_PERFORM:
00960                      /*
00961                       * FIXME: need to check if it may be considered 
00962                       * legal to trim values when adding/modifying;
00963                       * it should be when searching (e.g. ACLs).
00964                       */
00965                      ch_free( a_vals[i].bv_val );
00966                      if (last > i ) {
00967                             a_vals[i] = a_vals[last];
00968                             if ( pa_nvals ) {
00969                                    (*pa_nvals)[i] = (*pa_nvals)[last];
00970                             }
00971                      }
00972                      BER_BVZERO( &a_vals[last] );
00973                      if ( pa_nvals ) {
00974                             BER_BVZERO( &(*pa_nvals)[last] );
00975                      }
00976                      last--;
00977                      break;
00978               
00979               case LDAP_SUCCESS:
00980                      if ( !BER_BVISNULL( &dn ) && dn.bv_val != olddn.bv_val ) {
00981                             char   *newurl;
00982 
00983                             ludp->lud_dn = dn.bv_val;
00984                             newurl = ldap_url_desc2str( ludp );
00985                             ludp->lud_dn = olddn.bv_val;
00986                             ch_free( dn.bv_val );
00987                             if ( newurl == NULL ) {
00988                                    /* FIXME: leave attr untouched
00989                                     * even if ldap_url_desc2str failed...
00990                                     */
00991                                    break;
00992                             }
00993 
00994                             ber_str2bv( newurl, 0, 1, &a_vals[i] );
00995                             ber_memfree( newurl );
00996 
00997                             if ( pa_nvals ) {
00998                                    ludp->lud_dn = ndn.bv_val;
00999                                    newurl = ldap_url_desc2str( ludp );
01000                                    ludp->lud_dn = olddn.bv_val;
01001                                    ch_free( ndn.bv_val );
01002                                    if ( newurl == NULL ) {
01003                                           /* FIXME: leave attr untouched
01004                                            * even if ldap_url_desc2str failed...
01005                                            */
01006                                           ch_free( a_vals[i].bv_val );
01007                                           a_vals[i] = oldval;
01008                                           break;
01009                                    }
01010 
01011                                    if ( !BER_BVISNULL( &(*pa_nvals)[i] ) ) {
01012                                           ch_free( (*pa_nvals)[i].bv_val );
01013                                    }
01014                                    ber_str2bv( newurl, 0, 1, &(*pa_nvals)[i] );
01015                                    ber_memfree( newurl );
01016                             }
01017 
01018                             ch_free( oldval.bv_val );
01019                             ludp->lud_dn = olddn.bv_val;
01020                      }
01021                      break;
01022 
01023               default:
01024                      /* leave attr untouched if massage failed */
01025                      if ( pa_nvals && BER_BVISNULL( &(*pa_nvals)[i] ) ) {
01026                             ber_dupbv( &(*pa_nvals)[i], &a_vals[i] );
01027                      }
01028                      break;
01029               }
01030               ldap_free_urldesc( ludp );
01031        }
01032        
01033        return 0;
01034 }
01035 
01036 /*
01037  * I don't like this much, but we need two different
01038  * functions because different heap managers may be
01039  * in use in back-ldap/meta to reduce the amount of
01040  * calls to malloc routines, and some of the free()
01041  * routines may be macros with args
01042  */
01043 int
01044 rwm_dnattr_rewrite(
01045        Operation            *op,
01046        SlapReply            *rs,
01047        void                 *cookie,
01048        BerVarray            a_vals,
01049        BerVarray            *pa_nvals )
01050 {
01051        slap_overinst        *on = (slap_overinst *) op->o_bd->bd_info;
01052        struct ldaprwmap     *rwmap = 
01053                      (struct ldaprwmap *)on->on_bi.bi_private;
01054 
01055        int                  i, last;
01056 
01057        dncookie             dc;
01058        struct berval        dn = BER_BVNULL,
01059                             ndn = BER_BVNULL;
01060        BerVarray            in;
01061 
01062        if ( a_vals ) {
01063               in = a_vals;
01064 
01065        } else {
01066               if ( pa_nvals == NULL || *pa_nvals == NULL ) {
01067                      return LDAP_OTHER;
01068               }
01069               in = *pa_nvals;
01070        }
01071 
01072        /*
01073         * Rewrite the dn if needed
01074         */
01075        dc.rwmap = rwmap;
01076        dc.conn = op->o_conn;
01077        dc.rs = rs;
01078        dc.ctx = (char *)cookie;
01079 
01080        for ( last = 0; !BER_BVISNULL( &in[last] ); last++ );
01081        last--;
01082        if ( pa_nvals != NULL ) {
01083               if ( *pa_nvals == NULL ) {
01084                      *pa_nvals = ch_malloc( ( last + 2 ) * sizeof(struct berval) );
01085                      memset( *pa_nvals, 0, ( last + 2 ) * sizeof(struct berval) );
01086               }
01087        }
01088 
01089        for ( i = 0; !BER_BVISNULL( &in[i] ); i++ ) {
01090               int           rc;
01091 
01092               if ( a_vals ) {
01093                      dn = in[i];
01094                      if ( pa_nvals ) {
01095                             ndn = (*pa_nvals)[i];
01096                             rc = rwm_dn_massage_pretty_normalize( &dc, &in[i], &dn, &ndn );
01097                      } else {
01098                             rc = rwm_dn_massage_pretty( &dc, &in[i], &dn );
01099                      }
01100               } else {
01101                      ndn = in[i];
01102                      rc = rwm_dn_massage_normalize( &dc, &in[i], &ndn );
01103               }
01104 
01105               switch ( rc ) {
01106               case LDAP_UNWILLING_TO_PERFORM:
01107                      /*
01108                       * FIXME: need to check if it may be considered 
01109                       * legal to trim values when adding/modifying;
01110                       * it should be when searching (e.g. ACLs).
01111                       */
01112                      ch_free( in[i].bv_val );
01113                      if (last > i ) {
01114                             in[i] = in[last];
01115                             if ( a_vals && pa_nvals ) {
01116                                    (*pa_nvals)[i] = (*pa_nvals)[last];
01117                             }
01118                      }
01119                      BER_BVZERO( &in[last] );
01120                      if ( a_vals && pa_nvals ) {
01121                             BER_BVZERO( &(*pa_nvals)[last] );
01122                      }
01123                      last--;
01124                      break;
01125               
01126               case LDAP_SUCCESS:
01127                      if ( a_vals ) {
01128                             if ( !BER_BVISNULL( &dn ) && dn.bv_val != a_vals[i].bv_val ) {
01129                                    ch_free( a_vals[i].bv_val );
01130                                    a_vals[i] = dn;
01131 
01132                                    if ( pa_nvals ) {
01133                                           if ( !BER_BVISNULL( &(*pa_nvals)[i] ) ) {
01134                                                  ch_free( (*pa_nvals)[i].bv_val );
01135                                           }
01136                                           (*pa_nvals)[i] = ndn;
01137                                    }
01138                             }
01139                             
01140                      } else {
01141                             if ( !BER_BVISNULL( &ndn ) && ndn.bv_val != (*pa_nvals)[i].bv_val ) {
01142                                    ch_free( (*pa_nvals)[i].bv_val );
01143                                    (*pa_nvals)[i] = ndn;
01144                             }
01145                      }
01146                      break;
01147 
01148               default:
01149                      /* leave attr untouched if massage failed */
01150                      if ( a_vals && pa_nvals && BER_BVISNULL( &(*pa_nvals)[i] ) ) {
01151                             dnNormalize( 0, NULL, NULL, &a_vals[i], &(*pa_nvals)[i], NULL );
01152                      }
01153                      break;
01154               }
01155        }
01156        
01157        return 0;
01158 }
01159 
01160 int
01161 rwm_referral_result_rewrite(
01162        dncookie             *dc,
01163        BerVarray            a_vals )
01164 {
01165        int           i, last;
01166 
01167        for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ );
01168        last--;
01169 
01170        for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) {
01171               struct berval dn,
01172                             olddn = BER_BVNULL;
01173               int           rc;
01174               LDAPURLDesc   *ludp;
01175 
01176               rc = ldap_url_parse( a_vals[i].bv_val, &ludp );
01177               if ( rc != LDAP_URL_SUCCESS ) {
01178                      /* leave attr untouched if massage failed */
01179                      continue;
01180               }
01181 
01182               /* FIXME: URLs like "ldap:///dc=suffix" if passed
01183                * thru ldap_url_parse() and ldap_url_desc2str()
01184                * get rewritten as "ldap:///dc=suffix??base";
01185                * we don't want this to occur... */
01186               if ( ludp->lud_scope == LDAP_SCOPE_BASE ) {
01187                      ludp->lud_scope = LDAP_SCOPE_DEFAULT;
01188               }
01189 
01190               ber_str2bv( ludp->lud_dn, 0, 0, &olddn );
01191 
01192               dn = olddn;
01193               rc = rwm_dn_massage_pretty( dc, &olddn, &dn );
01194               switch ( rc ) {
01195               case LDAP_UNWILLING_TO_PERFORM:
01196                      /*
01197                       * FIXME: need to check if it may be considered 
01198                       * legal to trim values when adding/modifying;
01199                       * it should be when searching (e.g. ACLs).
01200                       */
01201                      ch_free( a_vals[i].bv_val );
01202                      if ( last > i ) {
01203                             a_vals[i] = a_vals[last];
01204                      }
01205                      BER_BVZERO( &a_vals[last] );
01206                      last--;
01207                      i--;
01208                      break;
01209 
01210               default:
01211                      /* leave attr untouched if massage failed */
01212                      if ( !BER_BVISNULL( &dn ) && olddn.bv_val != dn.bv_val ) {
01213                             char   *newurl;
01214 
01215                             ludp->lud_dn = dn.bv_val;
01216                             newurl = ldap_url_desc2str( ludp );
01217                             if ( newurl == NULL ) {
01218                                    /* FIXME: leave attr untouched
01219                                     * even if ldap_url_desc2str failed...
01220                                     */
01221                                    break;
01222                             }
01223 
01224                             ch_free( a_vals[i].bv_val );
01225                             ber_str2bv( newurl, 0, 1, &a_vals[i] );
01226                             ber_memfree( newurl );
01227                             ludp->lud_dn = olddn.bv_val;
01228                      }
01229                      break;
01230               }
01231 
01232               ldap_free_urldesc( ludp );
01233        }
01234 
01235        return 0;
01236 }
01237 
01238 int
01239 rwm_dnattr_result_rewrite(
01240        dncookie             *dc,
01241        BerVarray            a_vals,
01242        BerVarray            a_nvals )
01243 {
01244        int           i, last;
01245 
01246        for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ );
01247        last--;
01248 
01249        for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) {
01250               struct berval pdn, ndn = BER_BVNULL;
01251               int           rc;
01252               
01253               pdn = a_vals[i];
01254               rc = rwm_dn_massage_pretty_normalize( dc, &a_vals[i], &pdn, &ndn );
01255               switch ( rc ) {
01256               case LDAP_UNWILLING_TO_PERFORM:
01257                      /*
01258                       * FIXME: need to check if it may be considered 
01259                       * legal to trim values when adding/modifying;
01260                       * it should be when searching (e.g. ACLs).
01261                       */
01262                      assert( a_vals[i].bv_val != a_nvals[i].bv_val );
01263                      ch_free( a_vals[i].bv_val );
01264                      ch_free( a_nvals[i].bv_val );
01265                      if ( last > i ) {
01266                             a_vals[i] = a_vals[last];
01267                             a_nvals[i] = a_nvals[last];
01268                      }
01269                      BER_BVZERO( &a_vals[last] );
01270                      BER_BVZERO( &a_nvals[last] );
01271                      last--;
01272                      break;
01273 
01274               default:
01275                      /* leave attr untouched if massage failed */
01276                      if ( !BER_BVISNULL( &pdn ) && a_vals[i].bv_val != pdn.bv_val ) {
01277                             ch_free( a_vals[i].bv_val );
01278                             a_vals[i] = pdn;
01279                      }
01280                      if ( !BER_BVISNULL( &ndn ) && a_nvals[i].bv_val != ndn.bv_val ) {
01281                             ch_free( a_nvals[i].bv_val );
01282                             a_nvals[i] = ndn;
01283                      }
01284                      break;
01285               }
01286        }
01287 
01288        return 0;
01289 }
01290 
01291 void
01292 rwm_mapping_dst_free( void *v_mapping )
01293 {
01294        struct ldapmapping *mapping = v_mapping;
01295 
01296        if ( BER_BVISEMPTY( &mapping[0].m_dst ) ) {
01297               rwm_mapping_free( &mapping[ -1 ] );
01298        }
01299 }
01300 
01301 void
01302 rwm_mapping_free( void *v_mapping )
01303 {
01304        struct ldapmapping *mapping = v_mapping;
01305 
01306        if ( !BER_BVISNULL( &mapping[0].m_src ) ) {
01307               ch_free( mapping[0].m_src.bv_val );
01308        }
01309 
01310        if ( mapping[0].m_flags & RWMMAP_F_FREE_SRC ) {
01311               if ( mapping[0].m_flags & RWMMAP_F_IS_OC ) {
01312                      if ( mapping[0].m_src_oc ) {
01313                             ch_free( mapping[0].m_src_oc );
01314                      }
01315 
01316               } else {
01317                      if ( mapping[0].m_src_ad ) {
01318                             ch_free( mapping[0].m_src_ad );
01319                      }
01320               }
01321        }
01322 
01323        if ( !BER_BVISNULL( &mapping[0].m_dst ) ) {
01324               ch_free( mapping[0].m_dst.bv_val );
01325        }
01326 
01327        if ( mapping[0].m_flags & RWMMAP_F_FREE_DST ) {
01328               if ( mapping[0].m_flags & RWMMAP_F_IS_OC ) {
01329                      if ( mapping[0].m_dst_oc ) {
01330                             ch_free( mapping[0].m_dst_oc );
01331                      }
01332 
01333               } else {
01334                      if ( mapping[0].m_dst_ad ) {
01335                             ch_free( mapping[0].m_dst_ad );
01336                      }
01337               }
01338        }
01339 
01340        ch_free( mapping );
01341 
01342 }
01343 
01344 #endif /* SLAPD_OVER_RWM */