]> git.sur5r.net Git - openldap/commitdiff
ITS#7609 add per-target filter patterns
authorHoward Chu <hyc@openldap.org>
Mon, 27 May 2013 01:43:46 +0000 (18:43 -0700)
committerHoward Chu <hyc@openldap.org>
Mon, 27 May 2013 01:43:46 +0000 (18:43 -0700)
doc/man/man5/slapd-meta.5
servers/slapd/back-meta/back-meta.h
servers/slapd/back-meta/config.c
servers/slapd/back-meta/init.c
servers/slapd/back-meta/search.c

index 30d6b63d60f7cf948032b4b7117dc4f333bf6e8e..a4020b5178df37ea69b90e7c718ab4a3b9cceb6f 100644 (file)
@@ -338,6 +338,19 @@ The optional number marks target <target> as the default one, starting
 from 1.
 Target <target> must be defined.
 
+.TP
+.B filter <pattern>
+This directive allows specifying a
+.BR regex (5)
+pattern to indicate what search filter terms are actually served by a target.
+
+In a search request, if the search filter matches the \fIpattern\fP
+the target is considered while fulfilling the request; otherwise
+the target is ignored. There may be multiple occurrences of
+the
+.B filter
+directive for each target.
+
 .TP
 .B idassert\-authzFrom <authz-regexp>
 if defined, selects what
index 90104d82f5cfa58b0f5d847312b3f3225cf50eb5..341c05571a800954ecc58de1f4d55919a81d89ce 100644 (file)
@@ -278,6 +278,12 @@ typedef struct metasubtree_t {
        struct metasubtree_t *ms_next;
 } metasubtree_t;
 
+typedef struct metafilter_t {
+       struct metafilter_t *mf_next;
+       struct berval mf_regex_pattern;
+       regex_t mf_regex;
+} metafilter_t;
+
 typedef struct metacommon_t {
        int                             mc_version;
        int                             mc_nretries;
@@ -324,6 +330,7 @@ typedef struct metatarget_t {
        LDAP_URLLIST_PROC       *mt_urllist_f;
        void                    *mt_urllist_p;
 
+       metafilter_t    *mt_filter;
        metasubtree_t           *mt_subtree;
        /* F: subtree-include; T: subtree-exclude */
        int                     mt_subtree_exclude;
@@ -681,6 +688,9 @@ meta_back_map_free( struct ldapmap *lm );
 extern int
 meta_subtree_destroy( metasubtree_t *ms );
 
+extern void
+meta_filter_destroy( metafilter_t *mf );
+
 extern int
 meta_target_finish( metainfo_t *mi, metatarget_t *mt,
        const char *log, char *msg, size_t msize
index 81e6c355ea9702cc2691f1fa86964bc23f9014ff..0be9ed8de9461e34324decbb0fecc9e99298d384 100644 (file)
@@ -101,6 +101,7 @@ enum {
        LDAP_BACK_CFG_PSEUDOROOTDN,
        LDAP_BACK_CFG_PSEUDOROOTPW,
        LDAP_BACK_CFG_KEEPALIVE,
+       LDAP_BACK_CFG_FILTER,
 
        LDAP_BACK_CFG_LAST
 };
@@ -417,6 +418,15 @@ static ConfigTable metacfg[] = {
                        "SINGLE-VALUE )",
                NULL, NULL },
 
+       { "filter", "pattern", 2, 2, 0,
+               ARG_MAGIC|LDAP_BACK_CFG_FILTER,
+               meta_back_cf_gen, "( OLcfgDbAt:3.112 "
+                       "NAME 'olcDbFilter' "
+                       "DESC 'Filter regex pattern to include in target' "
+                       "EQUALITY caseExactMatch "
+                       "SYNTAX OMsDirectoryString )",
+               NULL, NULL },
+
        { NULL, NULL, 0, 0, 0, ARG_IGNORED,
                NULL, NULL, NULL, NULL }
 };
@@ -477,6 +487,7 @@ static ConfigOCs metaocs[] = {
                        "$ olcDbSubtreeInclude "
                        "$ olcDbTimeout "
                        "$ olcDbKeepalive "
+                       "$ olcDbFilter "
 
                        /* defaults may be inherited */
                        COMMON_ATTRS
@@ -729,6 +740,22 @@ meta_subtree_destroy( metasubtree_t *ms )
        return meta_subtree_free( ms );
 }
 
+static void
+meta_filter_free( metafilter_t *mf )
+{
+       regfree( &mf->mf_regex );
+       ber_memfree( mf->mf_regex_pattern.bv_val );
+       ch_free( mf );
+}
+
+void
+meta_filter_destroy( metafilter_t *mf )
+{
+       if ( mf->mf_next )
+               meta_filter_destroy( mf->mf_next );
+       meta_filter_free( mf );
+}
+
 static struct berval st_styles[] = {
        BER_BVC("subtree"),
        BER_BVC("children"),
@@ -1603,6 +1630,16 @@ meta_back_cf_gen( ConfigArgs *c )
                        rc = meta_subtree_unparse( c, mt );
                        break;
 
+               case LDAP_BACK_CFG_FILTER:
+                       if ( mt->mt_filter == NULL ) {
+                               rc = 1;
+                       } else {
+                               metafilter_t *mf;
+                               for ( mf = mt->mt_filter; mf; mf = mf->mf_next )
+                                       value_add_one( &c->rvalue_vals, &mf->mf_regex_pattern );
+                       }
+                       break;
+
                /* replaced by idassert */
                case LDAP_BACK_CFG_PSEUDOROOTDN:
                case LDAP_BACK_CFG_PSEUDOROOTPW:
@@ -1833,6 +1870,26 @@ meta_back_cf_gen( ConfigArgs *c )
                        }
                        break;
 
+               case LDAP_BACK_CFG_FILTER:
+                       if ( c->valx < 0 ) {
+                               meta_filter_destroy( mt->mt_filter );
+                               mt->mt_filter = NULL;
+                       } else {
+                               metafilter_t *mf, **mprev;
+                               for (i=0, mprev = &mt->mt_filter, mf = *mprev; mf; mf = *mprev) {
+                                       if ( i == c->valx ) {
+                                               *mprev = mf->mf_next;
+                                               meta_filter_free( mf );
+                                               break;
+                                       }
+                                       i++;
+                                       mprev = &mf->mf_next;
+                               }
+                               if ( i != c->valx )
+                                       rc = 1;
+                       }
+                       break;
+
                case LDAP_BACK_CFG_KEEPALIVE:
                        mt->mt_tls.sb_keepalive.sk_idle = 0;
                        mt->mt_tls.sb_keepalive.sk_probes = 0;
@@ -2081,6 +2138,25 @@ meta_back_cf_gen( ConfigArgs *c )
                }
                break;
 
+       case LDAP_BACK_CFG_FILTER: {
+               metafilter_t *mf, **m2;
+               mf = ch_malloc( sizeof( metafilter_t ));
+               rc = regcomp( &mf->mf_regex, c->argv[1], REG_EXTENDED );
+               if ( rc ) {
+                       char regerr[ SLAP_TEXT_BUFLEN ];
+                       regerror( rc, &mf->mf_regex, regerr, sizeof(regerr) );
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
+                               "regular expression \"%s\" bad because of %s",
+                               c->argv[1], regerr );
+                       ch_free( mf );
+                       return 1;
+               }
+               ber_str2bv( c->argv[1], 0, 1, &mf->mf_regex_pattern );
+               for ( m2 = &mt->mt_filter; *m2; m2 = &(*m2)->mf_next )
+                       ;
+               *m2 = mf;
+       } break;
+
        case LDAP_BACK_CFG_DEFAULT_T:
        /* default target directive */
                i = mi->mi_ntargets - 1;
index b6daaf1740275d7547dd56524ea025af71b8fa4a..42ca371f174e16e6b92dde46efafab35f70b3c44 100644 (file)
@@ -340,6 +340,10 @@ target_free(
                meta_subtree_destroy( mt->mt_subtree );
                mt->mt_subtree = NULL;
        }
+       if ( mt->mt_filter ) {
+               meta_filter_destroy( mt->mt_filter );
+               mt->mt_filter = NULL;
+       }
        if ( !BER_BVISNULL( &mt->mt_psuffix ) ) {
                free( mt->mt_psuffix.bv_val );
        }
index 9aabda0b233971555e1fed5337ea9335e78094d5..e0c6e910f63b5c0e2fe17216e3b3e4f2fdf4533f 100644 (file)
@@ -548,6 +548,20 @@ meta_back_search_start(
                }
        }
 
+       /* check filter expression */
+       if ( mt->mt_filter ) {
+               metafilter_t *mf;
+               for ( mf = mt->mt_filter; mf; mf = mf->mf_next ) {
+                       if ( regexec( &mf->mf_regex, op->ors_filterstr.bv_val, 0, NULL, 0 ) == 0 )
+                               break;
+               }
+               /* nothing matched, this target is no longer a candidate */
+               if ( !mf ) {
+                       retcode = META_SEARCH_NOT_CANDIDATE;
+                       goto doreturn;
+               }
+       }
+
        /* initiate dobind */
        retcode = meta_search_dobind_init( op, rs, mcp, candidate, candidates );