]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
ITS#9715 Deduplicate verbmasks implementation from slapd/lloadd
authorOndřej Kuzník <okuznik@symas.com>
Mon, 18 Oct 2021 16:19:35 +0000 (17:19 +0100)
committerHoward Chu <hyc@openldap.org>
Mon, 18 Oct 2021 16:49:38 +0000 (17:49 +0100)
servers/lloadd/Makefile_server.in
servers/lloadd/config.c
servers/slapd/Makefile.in
servers/slapd/config.c
servers/slapd/proto-slap.h
servers/slapd/verbs.c [new file with mode: 0644]

index b129695173577582b0f2336e290a49a7fe4309fa..2c46b63e9988915e53b4db537ac493f73dacb096 100644 (file)
@@ -23,7 +23,7 @@ NT_OBJS = ../slapd/nt_svc.o ../../libraries/liblutil/slapdmsg.res
 
 SRCS   += main.c value.c \
                  ../slapd/ch_malloc.c ../slapd/logging.c ../slapd/proxyp.c \
-                 ../slapd/sl_malloc.c ../slapd/user.c
+                 ../slapd/sl_malloc.c ../slapd/user.c ../slapd/verbs.c
 
 OBJS   = $(patsubst %.c,%.o,$(SRCS)) $(@PLAT@_OBJS)
 
index 65bb8d33e1a70227b48ab322b3df415f9dcdab31..ccc9160364f2913ffb099fce8e8cfd810decdf00 100644 (file)
@@ -2894,99 +2894,6 @@ lload_read_config( const char *fname, const char *dir )
     return lload_read_config_file( fname, 0, NULL, config_back_cf_table );
 }
 
-/* restrictops, allows, disallows, requires, loglevel */
-
-int
-bverb_to_mask( struct berval *bword, slap_verbmasks *v )
-{
-    int i;
-    for ( i = 0; !BER_BVISNULL( &v[i].word ); i++ ) {
-        if ( !ber_bvstrcasecmp( bword, &v[i].word ) ) break;
-    }
-    return i;
-}
-
-int
-verb_to_mask( const char *word, slap_verbmasks *v )
-{
-    struct berval bword;
-    ber_str2bv( word, 0, 0, &bword );
-    return bverb_to_mask( &bword, v );
-}
-
-int
-verbs_to_mask( int argc, char *argv[], slap_verbmasks *v, slap_mask_t *m )
-{
-    int i, j;
-    for ( i = 1; i < argc; i++ ) {
-        j = verb_to_mask( argv[i], v );
-        if ( BER_BVISNULL( &v[j].word ) ) return i;
-        while ( !v[j].mask )
-            j--;
-        *m |= v[j].mask;
-    }
-    return 0;
-}
-
-/* Mask keywords that represent multiple bits should occur before single
- * bit keywords in the verbmasks array.
- */
-int
-mask_to_verbs( slap_verbmasks *v, slap_mask_t m, BerVarray *bva )
-{
-    int i, rc = 1;
-
-    if ( m ) {
-        for ( i = 0; !BER_BVISNULL( &v[i].word ); i++ ) {
-            if ( !v[i].mask ) continue;
-            if ( (m & v[i].mask) == v[i].mask ) {
-                value_add_one( bva, &v[i].word );
-                rc = 0;
-                m ^= v[i].mask;
-                if ( !m ) break;
-            }
-        }
-    }
-    return rc;
-}
-
-int
-slap_verbmasks_init( slap_verbmasks **vp, slap_verbmasks *v )
-{
-    int i;
-
-    assert( *vp == NULL );
-
-    for ( i = 0; !BER_BVISNULL( &v[i].word ); i++ ) /* EMPTY */;
-
-    *vp = ch_calloc( i + 1, sizeof(slap_verbmasks) );
-
-    for ( i = 0; !BER_BVISNULL( &v[i].word ); i++ ) {
-        ber_dupbv( &(*vp)[i].word, &v[i].word );
-        *( (slap_mask_t *)&(*vp)[i].mask ) = v[i].mask;
-    }
-
-    BER_BVZERO( &(*vp)[i].word );
-
-    return 0;
-}
-
-int
-slap_verbmasks_destroy( slap_verbmasks *v )
-{
-    int i;
-
-    assert( v != NULL );
-
-    for ( i = 0; !BER_BVISNULL( &v[i].word ); i++ ) {
-        ch_free( v[i].word.bv_val );
-    }
-
-    ch_free( v );
-
-    return 0;
-}
-
 #ifndef BALANCER_MODULE
 int
 config_push_cleanup( ConfigArgs *ca, ConfigDriver *cleanup )
index 888ad54c583e81ca5c293274d0c05880b586b8fb..7b891f817c9b0b2d700719ab6ae816602892c3ab 100644 (file)
@@ -27,7 +27,7 @@ SRCS  = main.c globals.c bconfig.c config.c daemon.c \
                connection.c search.c filter.c add.c cr.c \
                attr.c entry.c backend.c result.c operation.c \
                dn.c compare.c modify.c delete.c modrdn.c ch_malloc.c \
-               value.c ava.c bind.c unbind.c abandon.c filterentry.c \
+               value.c verbs.c ava.c bind.c unbind.c abandon.c filterentry.c \
                phonetic.c acl.c str2filter.c aclparse.c init.c user.c \
                lock.c logging.c controls.c extended.c passwd.c proxyp.c \
                schema.c schema_check.c schema_init.c schema_prep.c \
@@ -45,7 +45,7 @@ OBJS  = main.o globals.o bconfig.o config.o daemon.o \
                connection.o search.o filter.o add.o cr.o \
                attr.o entry.o backend.o backends.o result.o operation.o \
                dn.o compare.o modify.o delete.o modrdn.o ch_malloc.o \
-               value.o ava.o bind.o unbind.o abandon.o filterentry.o \
+               value.o verbs.o ava.o bind.o unbind.o abandon.o filterentry.o \
                phonetic.o acl.o str2filter.o aclparse.o init.o user.o \
                lock.o logging.o controls.o extended.o passwd.o proxyp.o \
                schema.o schema_check.o schema_init.o schema_prep.o \
index 85a8eda5ec862a010b7c9e0cd0cea6eb3549451d..a8dcfb7bfa669aa992c41b6371b4c7c2de6514c3 100644 (file)
@@ -1022,258 +1022,6 @@ done:
 
 /* restrictops, allows, disallows, requires, loglevel */
 
-int
-bverb_to_mask(struct berval *bword, slap_verbmasks *v) {
-       int i;
-       for(i = 0; !BER_BVISNULL(&v[i].word); i++) {
-               if(!ber_bvstrcasecmp(bword, &v[i].word)) break;
-       }
-       return(i);
-}
-
-int
-verb_to_mask(const char *word, slap_verbmasks *v) {
-       struct berval   bword;
-       ber_str2bv( word, 0, 0, &bword );
-       return bverb_to_mask( &bword, v );
-}
-
-int
-verbs_to_mask(int argc, char *argv[], slap_verbmasks *v, slap_mask_t *m) {
-       int i, j;
-       for(i = 1; i < argc; i++) {
-               j = verb_to_mask(argv[i], v);
-               if(BER_BVISNULL(&v[j].word)) return i;
-               while (!v[j].mask) j--;
-               *m |= v[j].mask;
-       }
-       return(0);
-}
-
-/* Mask keywords that represent multiple bits should occur before single
- * bit keywords in the verbmasks array.
- */
-int
-mask_to_verbs(slap_verbmasks *v, slap_mask_t m, BerVarray *bva) {
-       int i, rc = 1;
-
-       if (m) {
-               for (i=0; !BER_BVISNULL(&v[i].word); i++) {
-                       if (!v[i].mask) continue;
-                       if (( m & v[i].mask ) == v[i].mask ) {
-                               value_add_one( bva, &v[i].word );
-                               rc = 0;
-                               m ^= v[i].mask;
-                               if ( !m ) break;
-                       }
-               }
-       }
-       return rc;
-}
-
-/* Return the verbs as a single string, separated by delim */
-int
-mask_to_verbstring(slap_verbmasks *v, slap_mask_t m0, char delim, struct berval *bv)
-{
-       int i, rc = 1;
-
-       BER_BVZERO( bv );
-       if (m0) {
-               slap_mask_t m = m0;
-               char *ptr;
-               for (i=0; !BER_BVISNULL(&v[i].word); i++) {
-                       if (!v[i].mask) continue;
-                       if (( m & v[i].mask ) == v[i].mask ) {
-                               bv->bv_len += v[i].word.bv_len + 1;
-                               rc = 0;
-                               m ^= v[i].mask;
-                               if ( !m ) break;
-                       }
-               }
-               bv->bv_val = ch_malloc(bv->bv_len);
-               bv->bv_len--;
-               ptr = bv->bv_val;
-               m = m0;
-               for (i=0; !BER_BVISNULL(&v[i].word); i++) {
-                       if (!v[i].mask) continue;
-                       if (( m & v[i].mask ) == v[i].mask ) {
-                               ptr = lutil_strcopy(ptr, v[i].word.bv_val);
-                               *ptr++ = delim;
-                               m ^= v[i].mask;
-                               if ( !m ) break;
-                       }
-               }
-               ptr[-1] = '\0';
-       }
-       return rc;
-}
-
-/* Parse a verbstring */
-int
-verbstring_to_mask(slap_verbmasks *v, char *str, char delim, slap_mask_t *m) {
-       int j;
-       char *d;
-       struct berval bv;
-
-       do {
-               bv.bv_val = str;
-               d = strchr( str, delim );
-               if ( d )
-                       bv.bv_len = d - str;
-               else
-                       bv.bv_len = strlen( str );
-               j = bverb_to_mask( &bv, v );
-               if(BER_BVISNULL(&v[j].word)) return 1;
-               while (!v[j].mask) j--;
-               *m |= v[j].mask;
-               str += bv.bv_len + 1;
-       } while ( d );
-       return(0);
-}
-
-int
-slap_verbmasks_init( slap_verbmasks **vp, slap_verbmasks *v )
-{
-       int             i;
-
-       assert( *vp == NULL );
-
-       for ( i = 0; !BER_BVISNULL( &v[ i ].word ); i++ ) /* EMPTY */;
-
-       *vp = ch_calloc( i + 1, sizeof( slap_verbmasks ) );
-
-       for ( i = 0; !BER_BVISNULL( &v[ i ].word ); i++ ) {
-               ber_dupbv( &(*vp)[ i ].word, &v[ i ].word );
-               *((slap_mask_t *)&(*vp)[ i ].mask) = v[ i ].mask;
-       }
-
-       BER_BVZERO( &(*vp)[ i ].word );
-
-       return 0;               
-}
-
-int
-slap_verbmasks_destroy( slap_verbmasks *v )
-{
-       int             i;
-
-       assert( v != NULL );
-
-       for ( i = 0; !BER_BVISNULL( &v[ i ].word ); i++ ) {
-               ch_free( v[ i ].word.bv_val );
-       }
-
-       ch_free( v );
-
-       return 0;
-}
-
-int
-slap_verbmasks_append(
-       slap_verbmasks  **vp,
-       slap_mask_t     m,
-       struct berval   *v,
-       slap_mask_t     *ignore )
-{
-       int     i;
-
-       if ( !m ) {
-               return LDAP_OPERATIONS_ERROR;
-       }
-
-       for ( i = 0; !BER_BVISNULL( &(*vp)[ i ].word ); i++ ) {
-               if ( !(*vp)[ i ].mask ) continue;
-
-               if ( ignore != NULL ) {
-                       int     j;
-
-                       for ( j = 0; ignore[ j ] != 0; j++ ) {
-                               if ( (*vp)[ i ].mask == ignore[ j ] ) {
-                                       goto check_next;
-                               }
-                       }
-               }
-
-               if ( ( m & (*vp)[ i ].mask ) == (*vp)[ i ].mask ) {
-                       if ( ber_bvstrcasecmp( v, &(*vp)[ i ].word ) == 0 ) {
-                               /* already set; ignore */
-                               return LDAP_SUCCESS;
-                       }
-                       /* conflicts */
-                       return LDAP_TYPE_OR_VALUE_EXISTS;
-               }
-
-               if ( m & (*vp)[ i ].mask ) {
-                       /* conflicts */
-                       return LDAP_CONSTRAINT_VIOLATION;
-               }
-check_next:;
-       }
-
-       *vp = ch_realloc( *vp, sizeof( slap_verbmasks ) * ( i + 2 ) );
-       ber_dupbv( &(*vp)[ i ].word, v );
-       *((slap_mask_t *)&(*vp)[ i ].mask) = m;
-       BER_BVZERO( &(*vp)[ i + 1 ].word );
-
-       return LDAP_SUCCESS;
-}
-
-int
-enum_to_verb(slap_verbmasks *v, slap_mask_t m, struct berval *bv) {
-       int i;
-
-       for (i=0; !BER_BVISNULL(&v[i].word); i++) {
-               if ( m == v[i].mask ) {
-                       if ( bv != NULL ) {
-                               *bv = v[i].word;
-                       }
-                       return i;
-               }
-       }
-       return -1;
-}
-
-/* register a new verbmask */
-static int
-slap_verbmask_register( slap_verbmasks *vm_, slap_verbmasks **vmp, struct berval *bv, int mask )
-{
-       slap_verbmasks  *vm = *vmp;
-       int             i;
-
-       /* check for duplicate word */
-       /* NOTE: we accept duplicate codes; the first occurrence will be used
-        * when mapping from mask to verb */
-       i = verb_to_mask( bv->bv_val, vm );
-       if ( !BER_BVISNULL( &vm[ i ].word ) ) {
-               return -1;
-       }
-
-       for ( i = 0; !BER_BVISNULL( &vm[ i ].word ); i++ )
-               ;
-
-       if ( vm == vm_ ) {
-               /* first time: duplicate array */
-               vm = ch_calloc( i + 2, sizeof( slap_verbmasks ) );
-               for ( i = 0; !BER_BVISNULL( &vm_[ i ].word ); i++ )
-               {
-                       ber_dupbv( &vm[ i ].word, &vm_[ i ].word );
-                       *((slap_mask_t*)&vm[ i ].mask) = vm_[ i ].mask;
-               }
-
-       } else {
-               vm = ch_realloc( vm, (i + 2) * sizeof( slap_verbmasks ) );
-       }
-
-       ber_dupbv( &vm[ i ].word, bv );
-       *((slap_mask_t*)&vm[ i ].mask) = mask;
-
-       BER_BVZERO( &vm[ i+1 ].word );
-
-       *vmp = vm;
-
-       return i;
-}
-
 static slap_verbmasks slap_ldap_response_code_[] = {
        { BER_BVC("success"),                           LDAP_SUCCESS },
 
index b93f309a1f093d5e5a5d5440064aa7adcc02f604..68f41fb2830cb46368157ff0c1817c8a1543fe59 100644 (file)
@@ -723,24 +723,6 @@ LDAP_SLAPD_F (int) read_config LDAP_P(( const char *fname, const char *dir ));
 LDAP_SLAPD_F (void) config_destroy LDAP_P ((void));
 LDAP_SLAPD_F (char **) slap_str2clist LDAP_P((
        char ***, char *, const char * ));
-LDAP_SLAPD_F (int) bverb_to_mask LDAP_P((
-       struct berval *bword,  slap_verbmasks *v ));
-LDAP_SLAPD_F (int) verb_to_mask LDAP_P((
-       const char *word,  slap_verbmasks *v ));
-LDAP_SLAPD_F (int) verbs_to_mask LDAP_P((
-       int argc, char *argv[], slap_verbmasks *v, slap_mask_t *m ));
-LDAP_SLAPD_F (int) mask_to_verbs LDAP_P((
-       slap_verbmasks *v, slap_mask_t m, BerVarray *bva ));
-LDAP_SLAPD_F (int) mask_to_verbstring LDAP_P((
-       slap_verbmasks *v, slap_mask_t m, char delim, struct berval *bv ));
-LDAP_SLAPD_F (int) verbstring_to_mask LDAP_P((
-       slap_verbmasks *v, char *str, char delim, slap_mask_t *m ));
-LDAP_SLAPD_F (int) enum_to_verb LDAP_P((
-       slap_verbmasks *v, slap_mask_t m, struct berval *bv ));
-LDAP_SLAPD_F (int) slap_verbmasks_init LDAP_P(( slap_verbmasks **vp, slap_verbmasks *v ));
-LDAP_SLAPD_F (int) slap_verbmasks_destroy LDAP_P(( slap_verbmasks *v ));
-LDAP_SLAPD_F (int) slap_verbmasks_append LDAP_P(( slap_verbmasks **vp,
-       slap_mask_t m, struct berval *v, slap_mask_t *ignore ));
 LDAP_SLAPD_F (int) slap_tls_get_config LDAP_P((
        LDAP *ld, int opt, char **val ));
 LDAP_SLAPD_F (void) bindconf_tls_defaults LDAP_P(( slap_bindconf *bc ));
@@ -2042,6 +2024,30 @@ LDAP_SLAPD_F (int) value_add_one LDAP_P((
 /* assumes (x) > (y) returns 1 if true, 0 otherwise */
 #define SLAP_PTRCMP(x, y) ((x) < (y) ? -1 : (x) > (y))
 
+/*
+ * verbs.c
+ */
+LDAP_SLAPD_F (int) bverb_to_mask LDAP_P((
+       struct berval *bword,  slap_verbmasks *v ));
+LDAP_SLAPD_F (int) verb_to_mask LDAP_P((
+       const char *word,  slap_verbmasks *v ));
+LDAP_SLAPD_F (int) verbs_to_mask LDAP_P((
+       int argc, char *argv[], slap_verbmasks *v, slap_mask_t *m ));
+LDAP_SLAPD_F (int) mask_to_verbs LDAP_P((
+       slap_verbmasks *v, slap_mask_t m, BerVarray *bva ));
+LDAP_SLAPD_F (int) mask_to_verbstring LDAP_P((
+       slap_verbmasks *v, slap_mask_t m, char delim, struct berval *bv ));
+LDAP_SLAPD_F (int) verbstring_to_mask LDAP_P((
+       slap_verbmasks *v, char *str, char delim, slap_mask_t *m ));
+LDAP_SLAPD_F (int) enum_to_verb LDAP_P((
+       slap_verbmasks *v, slap_mask_t m, struct berval *bv ));
+LDAP_SLAPD_F (int) slap_verbmasks_init LDAP_P(( slap_verbmasks **vp, slap_verbmasks *v ));
+LDAP_SLAPD_F (int) slap_verbmasks_destroy LDAP_P(( slap_verbmasks *v ));
+LDAP_SLAPD_F (int) slap_verbmasks_append LDAP_P(( slap_verbmasks **vp,
+       slap_mask_t m, struct berval *v, slap_mask_t *ignore ));
+LDAP_SLAPD_F (int) slap_verbmask_register LDAP_P(( slap_verbmasks *vm_,
+       slap_verbmasks **vmp, struct berval *bv, int mask ));
+
 #ifdef SLAP_ZONE_ALLOC
 /*
  * zn_malloc.c
diff --git a/servers/slapd/verbs.c b/servers/slapd/verbs.c
new file mode 100644 (file)
index 0000000..72439cd
--- /dev/null
@@ -0,0 +1,276 @@
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2021 The OpenLDAP Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+
+#include "portable.h"
+
+#include "slap.h"
+#include "slap-config.h"
+
+int
+bverb_to_mask( struct berval *bword, slap_verbmasks *v ) {
+       int i;
+       for ( i = 0; !BER_BVISNULL(&v[i].word); i++ ) {
+               if ( !ber_bvstrcasecmp( bword, &v[i].word) ) break;
+       }
+       return i;
+}
+
+int
+verb_to_mask( const char *word, slap_verbmasks *v ) {
+       struct berval   bword;
+       ber_str2bv( word, 0, 0, &bword );
+       return bverb_to_mask( &bword, v );
+}
+
+int
+verbs_to_mask( int argc, char *argv[], slap_verbmasks *v, slap_mask_t *m ) {
+       int i, j;
+       for (i = 1; i < argc; i++ ) {
+               j = verb_to_mask( argv[i], v );
+               if ( BER_BVISNULL(&v[j].word) ) return i;
+               while ( !v[j].mask ) j--;
+               *m |= v[j].mask;
+       }
+       return 0;
+}
+
+/*
+ * Mask keywords that represent multiple bits should occur before single
+ * bit keywords in the verbmasks array.
+ */
+int
+mask_to_verbs( slap_verbmasks *v, slap_mask_t m, BerVarray *bva ) {
+       int i, rc = 1;
+
+       if ( m ) {
+               for ( i=0; !BER_BVISNULL(&v[i].word); i++ ) {
+                       if (!v[i].mask) continue;
+                       if ( ( m & v[i].mask ) == v[i].mask ) {
+                               value_add_one( bva, &v[i].word );
+                               rc = 0;
+                               m ^= v[i].mask;
+                               if ( !m ) break;
+                       }
+               }
+       }
+       return rc;
+}
+
+/* Return the verbs as a single string, separated by delim */
+int
+mask_to_verbstring( slap_verbmasks *v, slap_mask_t m0, char delim, struct berval *bv )
+{
+       int i, rc = 1;
+
+       BER_BVZERO( bv );
+       if ( m0 ) {
+               slap_mask_t m = m0;
+               char *ptr;
+               for ( i=0; !BER_BVISNULL(&v[i].word); i++ ) {
+                       if ( !v[i].mask ) continue;
+                       if ( ( m & v[i].mask ) == v[i].mask ) {
+                               bv->bv_len += v[i].word.bv_len + 1;
+                               rc = 0;
+                               m ^= v[i].mask;
+                               if ( !m ) break;
+                       }
+               }
+               bv->bv_val = ch_malloc(bv->bv_len);
+               bv->bv_len--;
+               ptr = bv->bv_val;
+               m = m0;
+               for ( i=0; !BER_BVISNULL(&v[i].word); i++ ) {
+                       if ( !v[i].mask ) continue;
+                       if ( ( m & v[i].mask ) == v[i].mask ) {
+                               ptr = lutil_strcopy( ptr, v[i].word.bv_val );
+                               *ptr++ = delim;
+                               m ^= v[i].mask;
+                               if ( !m ) break;
+                       }
+               }
+               ptr[-1] = '\0';
+       }
+       return rc;
+}
+
+/* Parse a verbstring */
+int
+verbstring_to_mask( slap_verbmasks *v, char *str, char delim, slap_mask_t *m ) {
+       int j;
+       char *d;
+       struct berval bv;
+
+       do {
+               bv.bv_val = str;
+               d = strchr( str, delim );
+               if ( d )
+                       bv.bv_len = d - str;
+               else
+                       bv.bv_len = strlen( str );
+               j = bverb_to_mask( &bv, v );
+               if ( BER_BVISNULL(&v[j].word) ) return 1;
+               while ( !v[j].mask ) j--;
+               *m |= v[j].mask;
+               str += bv.bv_len + 1;
+       } while ( d );
+       return 0;
+}
+
+int
+slap_verbmasks_init( slap_verbmasks **vp, slap_verbmasks *v )
+{
+       int             i;
+
+       assert( *vp == NULL );
+
+       for ( i = 0; !BER_BVISNULL( &v[ i ].word ); i++ ) /* EMPTY */;
+
+       *vp = ch_calloc( i + 1, sizeof( slap_verbmasks ) );
+
+       for ( i = 0; !BER_BVISNULL( &v[ i ].word ); i++ ) {
+               ber_dupbv( &(*vp)[ i ].word, &v[ i ].word );
+               *((slap_mask_t *)&(*vp)[ i ].mask) = v[ i ].mask;
+       }
+
+       BER_BVZERO( &(*vp)[ i ].word );
+
+       return 0;
+}
+
+int
+slap_verbmasks_destroy( slap_verbmasks *v )
+{
+       int             i;
+
+       assert( v != NULL );
+
+       for ( i = 0; !BER_BVISNULL( &v[ i ].word ); i++ ) {
+               ch_free( v[ i ].word.bv_val );
+       }
+
+       ch_free( v );
+
+       return 0;
+}
+
+int
+slap_verbmasks_append(
+       slap_verbmasks  **vp,
+       slap_mask_t     m,
+       struct berval   *v,
+       slap_mask_t     *ignore )
+{
+       int     i;
+
+       if ( !m ) {
+               return LDAP_OPERATIONS_ERROR;
+       }
+
+       for ( i = 0; !BER_BVISNULL( &(*vp)[ i ].word ); i++ ) {
+               if ( !(*vp)[ i ].mask ) continue;
+
+               if ( ignore != NULL ) {
+                       int     j;
+
+                       for ( j = 0; ignore[ j ] != 0; j++ ) {
+                               if ( (*vp)[ i ].mask == ignore[ j ] ) {
+                                       goto check_next;
+                               }
+                       }
+               }
+
+               if ( ( m & (*vp)[ i ].mask ) == (*vp)[ i ].mask ) {
+                       if ( ber_bvstrcasecmp( v, &(*vp)[ i ].word ) == 0 ) {
+                               /* already set; ignore */
+                               return LDAP_SUCCESS;
+                       }
+                       /* conflicts */
+                       return LDAP_TYPE_OR_VALUE_EXISTS;
+               }
+
+               if ( m & (*vp)[ i ].mask ) {
+                       /* conflicts */
+                       return LDAP_CONSTRAINT_VIOLATION;
+               }
+check_next:;
+       }
+
+       *vp = ch_realloc( *vp, sizeof( slap_verbmasks ) * ( i + 2 ) );
+       ber_dupbv( &(*vp)[ i ].word, v );
+       *((slap_mask_t *)&(*vp)[ i ].mask) = m;
+       BER_BVZERO( &(*vp)[ i + 1 ].word );
+
+       return LDAP_SUCCESS;
+}
+
+int
+enum_to_verb(slap_verbmasks *v, slap_mask_t m, struct berval *bv) {
+       int i;
+
+       for (i=0; !BER_BVISNULL(&v[i].word); i++) {
+               if ( m == v[i].mask ) {
+                       if ( bv != NULL ) {
+                               *bv = v[i].word;
+                       }
+                       return i;
+               }
+       }
+       return -1;
+}
+
+/* register a new verbmask */
+int
+slap_verbmask_register(
+       slap_verbmasks *vm_,
+       slap_verbmasks **vmp,
+       struct berval *bv,
+       int mask )
+{
+       slap_verbmasks  *vm = *vmp;
+       int             i;
+
+       /* check for duplicate word */
+       /* NOTE: we accept duplicate codes; the first occurrence will be used
+        * when mapping from mask to verb */
+       i = verb_to_mask( bv->bv_val, vm );
+       if ( !BER_BVISNULL( &vm[ i ].word ) ) {
+               return -1;
+       }
+
+       for ( i = 0; !BER_BVISNULL( &vm[ i ].word ); i++ )
+               ;
+
+       if ( vm == vm_ ) {
+               /* first time: duplicate array */
+               vm = ch_calloc( i + 2, sizeof( slap_verbmasks ) );
+               for ( i = 0; !BER_BVISNULL( &vm_[ i ].word ); i++ )
+               {
+                       ber_dupbv( &vm[ i ].word, &vm_[ i ].word );
+                       *((slap_mask_t*)&vm[ i ].mask) = vm_[ i ].mask;
+               }
+
+       } else {
+               vm = ch_realloc( vm, (i + 2) * sizeof( slap_verbmasks ) );
+       }
+
+       ber_dupbv( &vm[ i ].word, bv );
+       *((slap_mask_t*)&vm[ i ].mask) = mask;
+
+       BER_BVZERO( &vm[ i+1 ].word );
+
+       *vmp = vm;
+
+       return i;
+}