}
 #endif
                
+               if ( a->a_desc->ad_type->sat_no_user_mod  ) {
+                       continue;
+               }
+
                ldap_back_map(&li->at_map, &a->a_desc->ad_cname, &mapped, 0);
                if (mapped.bv_val == NULL) {
                        continue;
 
                return( -1 );
        }
 
+       if ( op->o_ctrls ) {
+               ldap_set_option( lc->ld, LDAP_OPT_SERVER_CONTROLS, op->o_ctrls );
+       }
+       
        /*
         * Rewrite the bind dn if needed
         */
  * it can be used to simplify the check.
  */
 int
-ldap_back_dobind(struct ldapconn *lc, Operation *op)
+ldap_back_dobind( struct ldapconn *lc, Operation *op )
 {
-       if (lc->bound) {
+       if ( lc->bound ) {
                return( lc->bound );
        }
 
-       if (ldap_bind_s(lc->ld, lc->bound_dn.bv_val, lc->cred.bv_val, LDAP_AUTH_SIMPLE) !=
-               LDAP_SUCCESS) {
-               ldap_back_op_result(lc, op);
+       if ( op->o_ctrls ) {
+               ldap_set_option( lc->ld, LDAP_OPT_SERVER_CONTROLS,
+                               op->o_ctrls );
+       }
+       
+       if ( ldap_bind_s( lc->ld, lc->bound_dn.bv_val, lc->cred.bv_val, 
+                               LDAP_AUTH_SIMPLE ) != LDAP_SUCCESS ) {
+               ldap_back_op_result( lc, op );
                return( 0 );
        } /* else */
        return( lc->bound = 1 );
 
     BackendInfo        *bi
 )
 {
+       bi->bi_controls = slap_known_controls;
+
        bi->bi_open = 0;
        bi->bi_config = 0;
        bi->bi_close = 0;
 
        }
 
        for (i=0, ml=modlist; ml; ml=ml->sml_next) {
+               if ( ml->sml_desc->ad_type->sat_no_user_mod  ) {
+                       continue;
+               }
+
                ldap_back_map(&li->at_map, &ml->sml_desc->ad_cname, &mapped, 0);
                if (mapped.bv_val == NULL) {
                        continue;
 
                ldap_set_option( lc->ld, LDAP_OPT_TIMELIMIT, (void *)&tlimit);
        if (slimit != -1)
                ldap_set_option( lc->ld, LDAP_OPT_SIZELIMIT, (void *)&slimit);
-       
+
+
+       /*
+        * controls are set in ldap_back_dobind()
+        * 
+        * FIXME: in case of values return filter, we might want
+        * to map attrs and maybe rewrite value
+        */
        if ( !ldap_back_dobind( lc, op ) ) {
                return( -1 );
        }
                        continue;
                }
                
-               if (ber_scanf( &ber, "[W]", &attr->a_vals ) == LBER_ERROR ) {
+               if ( ber_scanf( &ber, "[W]", &attr->a_vals ) == LBER_ERROR
+                               || attr->a_vals == NULL ) {
+                       /*
+                        * Note: attr->a_vals can be null when using
+                        * values result filter
+                        */
                        attr->a_vals = &dummy;
+
                } else if ( attr->a_desc == slap_schema.si_ad_objectClass
                                || attr->a_desc == slap_schema.si_ad_structuralObjectClass ) {
                        int i, last;
-                       assert( attr->a_vals );
+
                        for ( last = 0; attr->a_vals[last].bv_val; last++ ) ;
                        for ( i = 0, bv = attr->a_vals; bv->bv_val; bv++, i++ ) {
                                ldap_back_map(&li->oc_map, bv, &mapped, 1);
                } else if ( strcmp( attr->a_desc->ad_type->sat_syntax->ssyn_oid,
                                        SLAPD_DN_SYNTAX ) == 0 ) {
                        int i;
-                       assert( attr->a_vals );
                        for ( i = 0, bv = attr->a_vals; bv->bv_val; bv++, i++ ) {
                                struct berval newval;
                                
 
 
        for ( i = 0, a = e->e_attrs; a; a = a->a_next ) {
                int j;
-               /*
-                * lastmod should always be <off>, so that
-                * creation/modification operational attrs
-                * of the target directory are used, if available
-                */
-#if 0
-               if ( !strcasecmp( a->a_desc->ad_cname.bv_val,
-                       slap_schema.si_ad_creatorsName->ad_cname.bv_val )
-                       || !strcasecmp( a->a_desc->ad_cname.bv_val,
-                       slap_schema.si_ad_createTimestamp->ad_cname.bv_val )
-                       || !strcasecmp( a->a_desc->ad_cname.bv_val,
-                       slap_schema.si_ad_modifiersName->ad_cname.bv_val )
-                       || !strcasecmp( a->a_desc->ad_cname.bv_val,
-                       slap_schema.si_ad_modifyTimestamp->ad_cname.bv_val )
-               ) {
+
+               if ( a->a_desc->ad_type->sat_no_user_mod  ) {
                        continue;
                }
-#endif
-               
+
                ldap_back_map( &li->targets[ candidate ]->at_map,
                                &a->a_desc->ad_cname, &mapped, 0);
                if ( mapped.bv_val == NULL ) {
 
        Avlnode                 *conntree;
 };
 
-extern int
-meta_back_do_single_bind(
-               struct metainfo         *li,
-               struct metaconn         *lc,
-               struct berval           *dn,
-               struct berval           *ndn,
-               struct berval           *cred,
-               int                     method,
-               int                     candidate
-);
-
-
 #define META_OP_ALLOW_MULTIPLE         0x00
 #define META_OP_REQUIRE_SINGLE         0x01
 #define META_OP_REQUIRE_ALL            0x02
 
 #include "../back-ldap/back-ldap.h"
 #include "back-meta.h"
 
+static int
+meta_back_do_single_bind(
+               struct metainfo         *li,
+               struct metaconn         *lc,
+               Operation               *op,
+               struct berval           *dn,
+               struct berval           *ndn,
+               struct berval           *cred,
+               int                     method,
+               int                     candidate
+);
+
 int
 meta_back_bind(
                Backend         *be,
                        realmethod = method;
                }
                
-               lerr = meta_back_do_single_bind( li, lc,
+               lerr = meta_back_do_single_bind( li, lc, op,
                                realdn, realndn, realcred, realmethod, i );
                if ( lerr != LDAP_SUCCESS ) {
                        err = lerr;
  *
  * attempts to perform a bind with creds
  */
-int
+static int
 meta_back_do_single_bind(
                struct metainfo         *li,
                struct metaconn         *lc,
+               Operation               *op,
                struct berval           *dn,
                struct berval           *ndn,
                struct berval           *cred,
                return LDAP_OTHER;
        }
 
+       if ( op->o_ctrls ) {
+               ldap_set_option( lc->conns[ candidate ].ld, 
+                               LDAP_OPT_SERVER_CONTROLS, op->o_ctrls );
+       }
+       
        rc = ldap_bind_s( lc->conns[ candidate ].ld, mdn.bv_val, cred->bv_val, method );
        if ( rc != LDAP_SUCCESS ) {
                rc = ldap_back_map_result( rc );
                        lsc->bound_dn.bv_val = NULL;
                        lsc->bound_dn.bv_len = 0;
                }
+               
+               if ( op->o_ctrls ) {
+                       ldap_set_option( lsc->ld, LDAP_OPT_SERVER_CONTROLS,
+                                       op->o_ctrls );
+               }
+       
                rc = ldap_bind_s( lsc->ld, 0, NULL, LDAP_AUTH_SIMPLE );
                if ( rc != LDAP_SUCCESS ) {
                        
 
                BackendInfo     *bi
 )
 {
+       bi->bi_controls = slap_known_controls;
+
        bi->bi_open = 0;
        bi->bi_config = 0;
        bi->bi_close = 0;
 
 
        for ( i = 0, ml = modlist; ml; ml = ml->sml_next ) {
                int j;
-               /*
-                * lastmod should always be <off>
-                */
-#if 0
-               if ( !strcasecmp( a->a_desc->ad_cname.bv_val,
-                       slap_schema.si_ad_creatorsName->ad_cname.bv_val )
-                       || !strcasecmp( a->a_desc->ad_cname.bv_val,
-                       slap_schema.si_ad_createTimestamp->ad_cname.bv_val )
-                       || !strcasecmp( a->a_desc->ad_cname.bv_val,
-                       slap_schema.si_ad_modifiersName->ad_cname.bv_val )
-                       || !strcasecmp( a->a_desc->ad_cname.bv_val,
-                       slap_schema.si_ad_modifyTimestamp->ad_cname.bv_val ) ) {
+
+               if ( ml->sml_desc->ad_type->sat_no_user_mod  ) {
                        continue;
                }
-#endif
 
                ldap_back_map( &li->targets[ candidate ]->at_map,
                                &ml->sml_desc->ad_cname, &mapped, 0 );
 
 static const char* slap_name = NULL;
 int slapMode = SLAP_UNDEFINED_MODE;
 
+/*
+ * all known control OIDs should be added to this list
+ */
+char *slap_known_controls[] = {
+#ifdef LDAP_CONTROL_REFERRALS
+       LDAP_CONTROL_REFERRALS,
+#endif /* LDAP_CONTROL_REFERRALS */
+
+#ifdef LDAP_CONTROL_MANAGEDSAIT
+       LDAP_CONTROL_MANAGEDSAIT,
+#endif /* LDAP_CONTROL_MANAGEDSAIT */
+
+#ifdef LDAP_CONTROL_SUBENTRIES
+       LDAP_CONTROL_SUBENTRIES,
+#endif /* LDAP_CONTROL_SUBENTRIES */
+
+#ifdef LDAP_CONTROL_NOOP
+       LDAP_CONTROL_NOOP,
+#endif /* LDAP_CONTROL_NOOP */
+
+#ifdef LDAP_CONTROL_DUPENT_REQUEST
+       LDAP_CONTROL_DUPENT_REQUEST,
+#endif /* LDAP_CONTROL_DUPENT_REQUEST */
+
+#ifdef LDAP_CONTROL_DUPENT_RESPONSE
+       LDAP_CONTROL_DUPENT_RESPONSE,
+#endif /* LDAP_CONTROL_DUPENT_RESPONSE */
+
+#ifdef LDAP_CONTROL_DUPENT_ENTRY
+       LDAP_CONTROL_DUPENT_ENTRY,
+#endif /* LDAP_CONTROL_DUPENT_ENTRY */
+
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+       LDAP_CONTROL_PAGEDRESULTS,
+#endif /* LDAP_CONTROL_PAGEDRESULTS */
+
+#ifdef LDAP_CONTROL_SORTREQUEST
+       LDAP_CONTROL_SORTREQUEST,
+#endif /* LDAP_CONTROL_SORTREQUEST */
+
+#ifdef LDAP_CONTROL_SORTRESPONSE
+       LDAP_CONTROL_SORTRESPONSE,
+#endif /* LDAP_CONTROL_SORTRESPONSE */
+
+#ifdef LDAP_CONTROL_VLVREQUEST
+       LDAP_CONTROL_VLVREQUEST,
+#endif /* LDAP_CONTROL_VLVREQUEST */
+
+#ifdef LDAP_CONTROL_VLVRESPONSE
+       LDAP_CONTROL_VLVRESPONSE,
+#endif /* LDAP_CONTROL_VLVRESPONSE */
+
+#ifdef LDAP_CONTROL_VALUESRETURNFILTER
+       LDAP_CONTROL_VALUESRETURNFILTER,
+#endif /* LDAP_CONTROL_VALUESRETURNFILTER */
+
+       NULL
+};
+
 int
 slap_init( int mode, const char *name )
 {
 
 LDAP_SLAPD_F (int)     slap_shutdown LDAP_P(( Backend *be ));
 LDAP_SLAPD_F (int)     slap_destroy LDAP_P((void));
 
+LDAP_SLAPD_V (char *)  slap_known_controls[];
+
 /*
  * kerberos.c
  */