diff --git a/servers/lloadd/Makefile_server.in b/servers/lloadd/Makefile_server.in index b129695173..2c46b63e99 100644 --- a/servers/lloadd/Makefile_server.in +++ b/servers/lloadd/Makefile_server.in @@ -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) diff --git a/servers/lloadd/config.c b/servers/lloadd/config.c index 65bb8d33e1..ccc9160364 100644 --- a/servers/lloadd/config.c +++ b/servers/lloadd/config.c @@ -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 ) diff --git a/servers/slapd/Makefile.in b/servers/slapd/Makefile.in index 888ad54c58..7b891f817c 100644 --- a/servers/slapd/Makefile.in +++ b/servers/slapd/Makefile.in @@ -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 \ diff --git a/servers/slapd/config.c b/servers/slapd/config.c index 85a8eda5ec..a8dcfb7bfa 100644 --- a/servers/slapd/config.c +++ b/servers/slapd/config.c @@ -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 }, diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index b93f309a1f..68f41fb283 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -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 index 0000000000..72439cd85e --- /dev/null +++ b/servers/slapd/verbs.c @@ -0,0 +1,276 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * 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 + * . + */ + +#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; +}