Home | History | Annotate | Line # | Download | only in slapi
      1 /*	$NetBSD: slapi_utils.c,v 1.4 2025/09/05 21:16:33 christos Exp $	*/
      2 
      3 /* $OpenLDAP$ */
      4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      5  *
      6  * Copyright 2002-2024 The OpenLDAP Foundation.
      7  * Portions Copyright 1997,2002-2003 IBM Corporation.
      8  * All rights reserved.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted only as authorized by the OpenLDAP
     12  * Public License.
     13  *
     14  * A copy of this license is available in the file LICENSE in the
     15  * top-level directory of the distribution or, alternatively, at
     16  * <http://www.OpenLDAP.org/license.html>.
     17  */
     18 /* ACKNOWLEDGEMENTS:
     19  * This work was initially developed by IBM Corporation for use in
     20  * IBM products and subsequently ported to OpenLDAP Software by
     21  * Steve Omrani.  Additional significant contributors include:
     22  *   Luke Howard
     23  */
     24 
     25 #include <sys/cdefs.h>
     26 __RCSID("$NetBSD: slapi_utils.c,v 1.4 2025/09/05 21:16:33 christos Exp $");
     27 
     28 #include "portable.h"
     29 
     30 #include <ac/string.h>
     31 #include <ac/stdarg.h>
     32 #include <ac/ctype.h>
     33 #include <ac/unistd.h>
     34 #include <lutil.h>
     35 
     36 #include <slap.h>
     37 #include <slapi.h>
     38 
     39 #ifdef _WIN32
     40 #include <winsock.h>
     41 #else
     42 #include <netdb.h>
     43 #endif
     44 
     45 #ifdef LDAP_SLAPI
     46 
     47 /*
     48  * server start time (should we use a struct timeval also in slapd?
     49  */
     50 static struct			timeval base_time;
     51 ldap_pvt_thread_mutex_t		slapi_hn_mutex;
     52 ldap_pvt_thread_mutex_t		slapi_time_mutex;
     53 
     54 struct slapi_mutex {
     55 	ldap_pvt_thread_mutex_t mutex;
     56 };
     57 
     58 struct slapi_condvar {
     59 	ldap_pvt_thread_cond_t cond;
     60 	ldap_pvt_thread_mutex_t mutex;
     61 };
     62 
     63 static int checkBVString(const struct berval *bv)
     64 {
     65 	ber_len_t i;
     66 
     67 	for ( i = 0; i < bv->bv_len; i++ ) {
     68 		if ( bv->bv_val[i] == '\0' )
     69 			return 0;
     70 	}
     71 	if ( bv->bv_val[i] != '\0' )
     72 		return 0;
     73 
     74 	return 1;
     75 }
     76 
     77 /*
     78  * This function converts an array of pointers to berval objects to
     79  * an array of berval objects.
     80  */
     81 
     82 int
     83 bvptr2obj(
     84 	struct berval	**bvptr,
     85 	BerVarray	*bvobj,
     86 	unsigned *num )
     87 {
     88 	int		rc = LDAP_SUCCESS;
     89 	int		i;
     90 	BerVarray	tmpberval;
     91 
     92 	if ( bvptr == NULL || *bvptr == NULL ) {
     93 		return LDAP_OTHER;
     94 	}
     95 
     96 	for ( i = 0; bvptr != NULL && bvptr[i] != NULL; i++ ) {
     97 		; /* EMPTY */
     98 	}
     99 	if ( num )
    100 		*num = i;
    101 
    102 	tmpberval = (BerVarray)slapi_ch_malloc( (i + 1)*sizeof(struct berval));
    103 	if ( tmpberval == NULL ) {
    104 		return LDAP_NO_MEMORY;
    105 	}
    106 
    107 	for ( i = 0; bvptr[i] != NULL; i++ ) {
    108 		tmpberval[i].bv_val = bvptr[i]->bv_val;
    109 		tmpberval[i].bv_len = bvptr[i]->bv_len;
    110 	}
    111 	tmpberval[i].bv_val = NULL;
    112 	tmpberval[i].bv_len = 0;
    113 
    114 	if ( rc == LDAP_SUCCESS ) {
    115 		*bvobj = tmpberval;
    116 	}
    117 
    118 	return rc;
    119 }
    120 
    121 Slapi_Entry *
    122 slapi_str2entry(
    123 	char		*s,
    124 	int		flags )
    125 {
    126 	return str2entry( s );
    127 }
    128 
    129 char *
    130 slapi_entry2str(
    131 	Slapi_Entry	*e,
    132 	int		*len )
    133 {
    134 	char		*ret = NULL;
    135 	char		*s;
    136 
    137 	ldap_pvt_thread_mutex_lock( &entry2str_mutex );
    138 	s = entry2str( e, len );
    139 	if ( s != NULL )
    140 		ret = slapi_ch_strdup( s );
    141 	ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
    142 
    143 	return ret;
    144 }
    145 
    146 char *
    147 slapi_entry_get_dn( Slapi_Entry *e )
    148 {
    149 	return e->e_name.bv_val;
    150 }
    151 
    152 int
    153 slapi_x_entry_get_id( Slapi_Entry *e )
    154 {
    155 	return e->e_id;
    156 }
    157 
    158 static int
    159 slapi_int_dn_pretty( struct berval *in, struct berval *out )
    160 {
    161 	Syntax		*syntax = slap_schema.si_syn_distinguishedName;
    162 
    163 	assert( syntax != NULL );
    164 
    165 	return (syntax->ssyn_pretty)( syntax, in, out, NULL );
    166 }
    167 
    168 static int
    169 slapi_int_dn_normalize( struct berval *in, struct berval *out )
    170 {
    171 	MatchingRule	*mr = slap_schema.si_mr_distinguishedNameMatch;
    172 	Syntax		*syntax = slap_schema.si_syn_distinguishedName;
    173 
    174 	assert( mr != NULL );
    175 
    176 	return (mr->smr_normalize)( 0, syntax, mr, in, out, NULL );
    177 }
    178 
    179 void
    180 slapi_entry_set_dn(
    181 	Slapi_Entry	*e,
    182 	char		*ldn )
    183 {
    184 	struct berval	dn = BER_BVNULL;
    185 
    186 	dn.bv_val = ldn;
    187 	dn.bv_len = strlen( ldn );
    188 
    189 	slapi_int_dn_pretty( &dn, &e->e_name );
    190 	slapi_int_dn_normalize( &dn, &e->e_nname );
    191 }
    192 
    193 Slapi_Entry *
    194 slapi_entry_dup( Slapi_Entry *e )
    195 {
    196 	return entry_dup( e );
    197 }
    198 
    199 int
    200 slapi_entry_attr_delete(
    201 	Slapi_Entry	*e,
    202 	char		*type )
    203 {
    204 	AttributeDescription	*ad = NULL;
    205 	const char		*text;
    206 
    207 	if ( slap_str2ad( type, &ad, &text ) != LDAP_SUCCESS ) {
    208 		return 1;	/* LDAP_NO_SUCH_ATTRIBUTE */
    209 	}
    210 
    211 	if ( attr_delete( &e->e_attrs, ad ) == LDAP_SUCCESS ) {
    212 		return 0;	/* attribute is deleted */
    213 	} else {
    214 		return -1;	/* something went wrong */
    215 	}
    216 }
    217 
    218 Slapi_Entry *
    219 slapi_entry_alloc( void )
    220 {
    221 	return (Slapi_Entry *)entry_alloc();
    222 }
    223 
    224 void
    225 slapi_entry_free( Slapi_Entry *e )
    226 {
    227 	if ( e != NULL )
    228 		entry_free( e );
    229 }
    230 
    231 int
    232 slapi_entry_attr_merge(
    233 	Slapi_Entry	*e,
    234 	char		*type,
    235 	struct berval	**vals )
    236 {
    237 	AttributeDescription	*ad = NULL;
    238 	const char		*text;
    239 	BerVarray		bv;
    240 	int			rc;
    241 
    242 	rc = slap_str2ad( type, &ad, &text );
    243 	if ( rc != LDAP_SUCCESS ) {
    244 		return -1;
    245 	}
    246 
    247 	rc = bvptr2obj( vals, &bv, NULL );
    248 	if ( rc != LDAP_SUCCESS ) {
    249 		return -1;
    250 	}
    251 
    252 	rc = attr_merge_normalize( e, ad, bv, NULL );
    253 	ch_free( bv );
    254 
    255 	return rc;
    256 }
    257 
    258 int
    259 slapi_entry_attr_find(
    260 	Slapi_Entry	*e,
    261 	char		*type,
    262 	Slapi_Attr	**attr )
    263 {
    264 	AttributeDescription	*ad = NULL;
    265 	const char		*text;
    266 	int			rc;
    267 
    268 	rc = slap_str2ad( type, &ad, &text );
    269 	if ( rc != LDAP_SUCCESS ) {
    270 		return -1;
    271 	}
    272 
    273 	*attr = attr_find( e->e_attrs, ad );
    274 	if ( *attr == NULL ) {
    275 		return -1;
    276 	}
    277 
    278 	return 0;
    279 }
    280 
    281 char *
    282 slapi_entry_attr_get_charptr( const Slapi_Entry *e, const char *type )
    283 {
    284 	AttributeDescription *ad = NULL;
    285 	const char *text;
    286 	int rc;
    287 	Attribute *attr;
    288 
    289 	rc = slap_str2ad( type, &ad, &text );
    290 	if ( rc != LDAP_SUCCESS ) {
    291 		return NULL;
    292 	}
    293 
    294 	attr = attr_find( e->e_attrs, ad );
    295 	if ( attr == NULL ) {
    296 		return NULL;
    297 	}
    298 
    299 	if ( attr->a_vals != NULL && attr->a_vals[0].bv_len != 0 ) {
    300 		const char *p;
    301 
    302 		p = slapi_value_get_string( &attr->a_vals[0] );
    303 		if ( p != NULL ) {
    304 			return slapi_ch_strdup( p );
    305 		}
    306 	}
    307 
    308 	return NULL;
    309 }
    310 
    311 int
    312 slapi_entry_attr_get_int( const Slapi_Entry *e, const char *type )
    313 {
    314 	AttributeDescription *ad = NULL;
    315 	const char *text;
    316 	int rc;
    317 	Attribute *attr;
    318 
    319 	rc = slap_str2ad( type, &ad, &text );
    320 	if ( rc != LDAP_SUCCESS ) {
    321 		return 0;
    322 	}
    323 
    324 	attr = attr_find( e->e_attrs, ad );
    325 	if ( attr == NULL ) {
    326 		return 0;
    327 	}
    328 
    329 	return slapi_value_get_int( attr->a_vals );
    330 }
    331 
    332 long
    333 slapi_entry_attr_get_long( const Slapi_Entry *e, const char *type )
    334 {
    335 	AttributeDescription *ad = NULL;
    336 	const char *text;
    337 	int rc;
    338 	Attribute *attr;
    339 
    340 	rc = slap_str2ad( type, &ad, &text );
    341 	if ( rc != LDAP_SUCCESS ) {
    342 		return 0;
    343 	}
    344 
    345 	attr = attr_find( e->e_attrs, ad );
    346 	if ( attr == NULL ) {
    347 		return 0;
    348 	}
    349 
    350 	return slapi_value_get_long( attr->a_vals );
    351 }
    352 
    353 unsigned int
    354 slapi_entry_attr_get_uint( const Slapi_Entry *e, const char *type )
    355 {
    356 	AttributeDescription *ad = NULL;
    357 	const char *text;
    358 	int rc;
    359 	Attribute *attr;
    360 
    361 	rc = slap_str2ad( type, &ad, &text );
    362 	if ( rc != LDAP_SUCCESS ) {
    363 		return 0;
    364 	}
    365 
    366 	attr = attr_find( e->e_attrs, ad );
    367 	if ( attr == NULL ) {
    368 		return 0;
    369 	}
    370 
    371 	return slapi_value_get_uint( attr->a_vals );
    372 }
    373 
    374 unsigned long
    375 slapi_entry_attr_get_ulong( const Slapi_Entry *e, const char *type )
    376 {
    377 	AttributeDescription *ad = NULL;
    378 	const char *text;
    379 	int rc;
    380 	Attribute *attr;
    381 
    382 	rc = slap_str2ad( type, &ad, &text );
    383 	if ( rc != LDAP_SUCCESS ) {
    384 		return 0;
    385 	}
    386 
    387 	attr = attr_find( e->e_attrs, ad );
    388 	if ( attr == NULL ) {
    389 		return 0;
    390 	}
    391 
    392 	return slapi_value_get_ulong( attr->a_vals );
    393 }
    394 
    395 int
    396 slapi_entry_attr_hasvalue( Slapi_Entry *e, const char *type, const char *value )
    397 {
    398 	struct berval bv;
    399 	AttributeDescription *ad = NULL;
    400 	const char *text;
    401 	int rc;
    402 	Attribute *attr;
    403 
    404 	rc = slap_str2ad( type, &ad, &text );
    405 	if ( rc != LDAP_SUCCESS ) {
    406 		return 0;
    407 	}
    408 
    409 	attr = attr_find( e->e_attrs, ad );
    410 	if ( attr == NULL ) {
    411 		return 0;
    412 	}
    413 
    414 	bv.bv_val = (char *)value;
    415 	bv.bv_len = strlen( value );
    416 
    417 	return ( slapi_attr_value_find( attr, &bv ) != -1 );
    418 }
    419 
    420 void
    421 slapi_entry_attr_set_charptr(Slapi_Entry* e, const char *type, const char *value)
    422 {
    423 	AttributeDescription	*ad = NULL;
    424 	const char		*text;
    425 	int			rc;
    426 	struct berval		bv;
    427 
    428 	rc = slap_str2ad( type, &ad, &text );
    429 	if ( rc != LDAP_SUCCESS ) {
    430 		return;
    431 	}
    432 
    433 	attr_delete ( &e->e_attrs, ad );
    434 	if ( value != NULL ) {
    435 		bv.bv_val = (char *)value;
    436 		bv.bv_len = strlen(value);
    437 		attr_merge_normalize_one( e, ad, &bv, NULL );
    438 	}
    439 }
    440 
    441 void
    442 slapi_entry_attr_set_int( Slapi_Entry* e, const char *type, int l)
    443 {
    444 	char buf[64];
    445 
    446 	snprintf( buf, sizeof( buf ), "%d", l );
    447 	slapi_entry_attr_set_charptr( e, type, buf );
    448 }
    449 
    450 void
    451 slapi_entry_attr_set_uint( Slapi_Entry* e, const char *type, unsigned int l)
    452 {
    453 	char buf[64];
    454 
    455 	snprintf( buf, sizeof( buf ), "%u", l );
    456 	slapi_entry_attr_set_charptr( e, type, buf );
    457 }
    458 
    459 void
    460 slapi_entry_attr_set_long(Slapi_Entry* e, const char *type, long l)
    461 {
    462 	char buf[64];
    463 
    464 	snprintf( buf, sizeof( buf ), "%ld", l );
    465 	slapi_entry_attr_set_charptr( e, type, buf );
    466 }
    467 
    468 void
    469 slapi_entry_attr_set_ulong(Slapi_Entry* e, const char *type, unsigned long l)
    470 {
    471 	char buf[64];
    472 
    473 	snprintf( buf, sizeof( buf ), "%lu", l );
    474 	slapi_entry_attr_set_charptr( e, type, buf );
    475 }
    476 
    477 int
    478 slapi_is_rootdse( const char *dn )
    479 {
    480 	return ( dn == NULL || dn[0] == '\0' );
    481 }
    482 
    483 int
    484 slapi_entry_has_children( const Slapi_Entry *e )
    485 {
    486 	Slapi_PBlock *pb;
    487 	Backend *be = select_backend( (struct berval *)&e->e_nname, 0 );
    488 	int rc, hasSubordinates = 0;
    489 
    490 	if ( be == NULL || be->be_has_subordinates == 0 ) {
    491 		return 0;
    492 	}
    493 
    494 	pb = slapi_pblock_new();
    495 	if ( pb == NULL ) {
    496 		return 0;
    497 	}
    498 	slapi_int_connection_init_pb( pb, LDAP_REQ_SEARCH );
    499 
    500 	rc = slapi_pblock_set( pb, SLAPI_TARGET_DN, slapi_entry_get_dn(
    501 		(Entry *) e ));
    502 	if ( rc == LDAP_SUCCESS ) {
    503 		pb->pb_op->o_bd = be;
    504 		rc = be->be_has_subordinates( pb->pb_op, (Entry *) e,
    505 			&hasSubordinates );
    506 	}
    507 
    508 	slapi_pblock_destroy( pb );
    509 
    510 	return ( rc == LDAP_SUCCESS && hasSubordinates == LDAP_COMPARE_TRUE );
    511 }
    512 
    513 /*
    514  * Return approximate size of the entry rounded to the nearest
    515  * 1K. Only the size of the attribute values are counted in the
    516  * Sun implementation.
    517  *
    518  * http://docs.sun.com/source/816-6701-10/funcref.html#1017388
    519  */
    520 size_t slapi_entry_size(Slapi_Entry *e)
    521 {
    522 	size_t size;
    523 	Attribute *a;
    524 	int i;
    525 
    526 	for ( size = 0, a = e->e_attrs; a != NULL; a = a->a_next ) {
    527 		for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
    528 			size += a->a_vals[i].bv_len + 1;
    529 		}
    530 	}
    531 
    532 	size += 1023;
    533 	size -= (size % 1024);
    534 
    535 	return size;
    536 }
    537 
    538 /*
    539  * Add values to entry.
    540  *
    541  * Returns:
    542  *	LDAP_SUCCESS			Values added to entry
    543  *	LDAP_TYPE_OR_VALUE_EXISTS	One or more values exist in entry already
    544  *	LDAP_CONSTRAINT_VIOLATION	Any other error (odd, but it's the spec)
    545  */
    546 int
    547 slapi_entry_add_values( Slapi_Entry *e, const char *type, struct berval **vals )
    548 {
    549 	Modification		mod;
    550 	const char		*text;
    551 	int			rc;
    552 	char			textbuf[SLAP_TEXT_BUFLEN];
    553 
    554 	mod.sm_op = LDAP_MOD_ADD;
    555 	mod.sm_flags = 0;
    556 	mod.sm_desc = NULL;
    557 	mod.sm_type.bv_val = (char *)type;
    558 	mod.sm_type.bv_len = strlen( type );
    559 
    560 	rc = slap_str2ad( type, &mod.sm_desc, &text );
    561 	if ( rc != LDAP_SUCCESS ) {
    562 		return rc;
    563 	}
    564 
    565 	if ( vals == NULL ) {
    566 		/* Apparently vals can be NULL
    567 		 * FIXME: sm_values = NULL ? */
    568 		mod.sm_values = (BerVarray)ch_malloc( sizeof(struct berval) );
    569 		mod.sm_values->bv_val = NULL;
    570 		mod.sm_numvals = 0;
    571 
    572 	} else {
    573 		rc = bvptr2obj( vals, &mod.sm_values, &mod.sm_numvals );
    574 		if ( rc != LDAP_SUCCESS ) {
    575 			return LDAP_CONSTRAINT_VIOLATION;
    576 		}
    577 	}
    578 	mod.sm_nvalues = NULL;
    579 
    580 	rc = modify_add_values( e, &mod, 0, &text, textbuf, sizeof(textbuf) );
    581 
    582 	slapi_ch_free( (void **)&mod.sm_values );
    583 
    584 	return (rc == LDAP_SUCCESS) ? LDAP_SUCCESS : LDAP_CONSTRAINT_VIOLATION;
    585 }
    586 
    587 int
    588 slapi_entry_add_values_sv( Slapi_Entry *e, const char *type, Slapi_Value **vals )
    589 {
    590 	return slapi_entry_add_values( e, type, vals );
    591 }
    592 
    593 int
    594 slapi_entry_add_valueset(Slapi_Entry *e, const char *type, Slapi_ValueSet *vs)
    595 {
    596 	AttributeDescription	*ad = NULL;
    597 	const char		*text;
    598 	int			rc;
    599 
    600 	rc = slap_str2ad( type, &ad, &text );
    601 	if ( rc != LDAP_SUCCESS ) {
    602 		return -1;
    603 	}
    604 
    605 	return attr_merge_normalize( e, ad, *vs, NULL );
    606 }
    607 
    608 int
    609 slapi_entry_delete_values( Slapi_Entry *e, const char *type, struct berval **vals )
    610 {
    611 	Modification		mod;
    612 	const char		*text;
    613 	int			rc;
    614 	char			textbuf[SLAP_TEXT_BUFLEN];
    615 
    616 	mod.sm_op = LDAP_MOD_DELETE;
    617 	mod.sm_flags = 0;
    618 	mod.sm_desc = NULL;
    619 	mod.sm_type.bv_val = (char *)type;
    620 	mod.sm_type.bv_len = strlen( type );
    621 
    622 	if ( vals == NULL ) {
    623 		/* If vals is NULL, this is a NOOP. */
    624 		return LDAP_SUCCESS;
    625 	}
    626 
    627 	rc = slap_str2ad( type, &mod.sm_desc, &text );
    628 	if ( rc != LDAP_SUCCESS ) {
    629 		return rc;
    630 	}
    631 
    632 	if ( vals[0] == NULL ) {
    633 		/* SLAPI doco says LDApb_opERATIONS_ERROR but LDAP_OTHER is better */
    634 		return attr_delete( &e->e_attrs, mod.sm_desc ) ? LDAP_OTHER : LDAP_SUCCESS;
    635 	}
    636 
    637 	rc = bvptr2obj( vals, &mod.sm_values, &mod.sm_numvals );
    638 	if ( rc != LDAP_SUCCESS ) {
    639 		return LDAP_CONSTRAINT_VIOLATION;
    640 	}
    641 	mod.sm_nvalues = NULL;
    642 
    643 	rc = modify_delete_values( e, &mod, 0, &text, textbuf, sizeof(textbuf) );
    644 
    645 	slapi_ch_free( (void **)&mod.sm_values );
    646 
    647 	return rc;
    648 }
    649 
    650 int
    651 slapi_entry_delete_values_sv( Slapi_Entry *e, const char *type, Slapi_Value **vals )
    652 {
    653 	return slapi_entry_delete_values( e, type, vals );
    654 }
    655 
    656 int
    657 slapi_entry_merge_values_sv( Slapi_Entry *e, const char *type, Slapi_Value **vals )
    658 {
    659 	return slapi_entry_attr_merge( e, (char *)type, vals );
    660 }
    661 
    662 int
    663 slapi_entry_add_value(Slapi_Entry *e, const char *type, const Slapi_Value *value)
    664 {
    665 	AttributeDescription	*ad = NULL;
    666 	int 			rc;
    667 	const char		*text;
    668 
    669 	rc = slap_str2ad( type, &ad, &text );
    670 	if ( rc != LDAP_SUCCESS ) {
    671 		return -1;
    672 	}
    673 
    674 	rc = attr_merge_normalize_one( e, ad, (Slapi_Value *)value, NULL );
    675 	if ( rc != LDAP_SUCCESS ) {
    676 		return -1;
    677 	}
    678 
    679 	return 0;
    680 }
    681 
    682 int
    683 slapi_entry_add_string(Slapi_Entry *e, const char *type, const char *value)
    684 {
    685 	Slapi_Value val;
    686 
    687 	val.bv_val = (char *)value;
    688 	val.bv_len = strlen( value );
    689 
    690 	return slapi_entry_add_value( e, type, &val );
    691 }
    692 
    693 int
    694 slapi_entry_delete_string(Slapi_Entry *e, const char *type, const char *value)
    695 {
    696 	Slapi_Value *vals[2];
    697 	Slapi_Value val;
    698 
    699 	val.bv_val = (char *)value;
    700 	val.bv_len = strlen( value );
    701 	vals[0] = &val;
    702 	vals[1] = NULL;
    703 
    704 	return slapi_entry_delete_values_sv( e, type, vals );
    705 }
    706 
    707 int
    708 slapi_entry_attr_merge_sv( Slapi_Entry *e, const char *type, Slapi_Value **vals )
    709 {
    710 	return slapi_entry_attr_merge( e, (char *)type, vals );
    711 }
    712 
    713 int
    714 slapi_entry_first_attr( const Slapi_Entry *e, Slapi_Attr **attr )
    715 {
    716 	if ( e == NULL ) {
    717 		return -1;
    718 	}
    719 
    720 	*attr = e->e_attrs;
    721 
    722 	return ( *attr != NULL ) ? 0 : -1;
    723 }
    724 
    725 int
    726 slapi_entry_next_attr( const Slapi_Entry *e, Slapi_Attr *prevattr, Slapi_Attr **attr )
    727 {
    728 	if ( e == NULL ) {
    729 		return -1;
    730 	}
    731 
    732 	if ( prevattr == NULL ) {
    733 		return -1;
    734 	}
    735 
    736 	*attr = prevattr->a_next;
    737 
    738 	return ( *attr != NULL ) ? 0 : -1;
    739 }
    740 
    741 int
    742 slapi_entry_attr_replace_sv( Slapi_Entry *e, const char *type, Slapi_Value **vals )
    743 {
    744 	AttributeDescription *ad = NULL;
    745 	const char *text;
    746 	int rc;
    747 	BerVarray bv;
    748 
    749 	rc = slap_str2ad( type, &ad, &text );
    750 	if ( rc != LDAP_SUCCESS ) {
    751 		return 0;
    752 	}
    753 
    754 	attr_delete( &e->e_attrs, ad );
    755 
    756 	rc = bvptr2obj( vals, &bv, NULL );
    757 	if ( rc != LDAP_SUCCESS ) {
    758 		return -1;
    759 	}
    760 
    761 	rc = attr_merge_normalize( e, ad, bv, NULL );
    762 	slapi_ch_free( (void **)&bv );
    763 	if ( rc != LDAP_SUCCESS ) {
    764 		return -1;
    765 	}
    766 
    767 	return 0;
    768 }
    769 
    770 /*
    771  * FIXME -- The caller must free the allocated memory.
    772  * In Netscape they do not have to.
    773  */
    774 int
    775 slapi_attr_get_values(
    776 	Slapi_Attr	*attr,
    777 	struct berval	***vals )
    778 {
    779 	int		i, j;
    780 	struct berval	**bv;
    781 
    782 	if ( attr == NULL ) {
    783 		return 1;
    784 	}
    785 
    786 	for ( i = 0; attr->a_vals[i].bv_val != NULL; i++ ) {
    787 		; /* EMPTY */
    788 	}
    789 
    790 	bv = (struct berval **)ch_malloc( (i + 1) * sizeof(struct berval *) );
    791 	for ( j = 0; j < i; j++ ) {
    792 		bv[j] = ber_dupbv( NULL, &attr->a_vals[j] );
    793 	}
    794 	bv[j] = NULL;
    795 
    796 	*vals = (struct berval **)bv;
    797 
    798 	return 0;
    799 }
    800 
    801 char *
    802 slapi_dn_normalize( char *dn )
    803 {
    804 	struct berval	bdn;
    805 	struct berval	pdn;
    806 
    807 	assert( dn != NULL );
    808 
    809 	bdn.bv_val = dn;
    810 	bdn.bv_len = strlen( dn );
    811 
    812 	if ( slapi_int_dn_pretty( &bdn, &pdn ) != LDAP_SUCCESS ) {
    813 		return NULL;
    814 	}
    815 
    816 	return pdn.bv_val;
    817 }
    818 
    819 char *
    820 slapi_dn_normalize_case( char *dn )
    821 {
    822 	struct berval	bdn;
    823 	struct berval	ndn;
    824 
    825 	assert( dn != NULL );
    826 
    827 	bdn.bv_val = dn;
    828 	bdn.bv_len = strlen( dn );
    829 
    830 	if ( slapi_int_dn_normalize( &bdn, &ndn ) != LDAP_SUCCESS ) {
    831 		return NULL;
    832 	}
    833 
    834 	return ndn.bv_val;
    835 }
    836 
    837 int
    838 slapi_dn_issuffix(
    839 	char		*dn,
    840 	char		*suffix )
    841 {
    842 	struct berval	bdn, ndn;
    843 	struct berval	bsuffix, nsuffix;
    844 	int rc;
    845 
    846 	assert( dn != NULL );
    847 	assert( suffix != NULL );
    848 
    849 	bdn.bv_val = dn;
    850 	bdn.bv_len = strlen( dn );
    851 
    852 	bsuffix.bv_val = suffix;
    853 	bsuffix.bv_len = strlen( suffix );
    854 
    855 	if ( dnNormalize( 0, NULL, NULL, &bdn, &ndn, NULL ) != LDAP_SUCCESS ) {
    856 		return 0;
    857 	}
    858 
    859 	if ( dnNormalize( 0, NULL, NULL, &bsuffix, &nsuffix, NULL )
    860 		!= LDAP_SUCCESS )
    861 	{
    862 		slapi_ch_free( (void **)&ndn.bv_val );
    863 		return 0;
    864 	}
    865 
    866 	rc = dnIsSuffix( &ndn, &nsuffix );
    867 
    868 	slapi_ch_free( (void **)&ndn.bv_val );
    869 	slapi_ch_free( (void **)&nsuffix.bv_val );
    870 
    871 	return rc;
    872 }
    873 
    874 int
    875 slapi_dn_isparent(
    876 	const char	*parentdn,
    877 	const char	*childdn )
    878 {
    879 	struct berval	assertedParentDN, normalizedAssertedParentDN;
    880 	struct berval	childDN, normalizedChildDN;
    881 	struct berval	normalizedParentDN;
    882 	int		match;
    883 
    884 	assert( parentdn != NULL );
    885 	assert( childdn != NULL );
    886 
    887 	assertedParentDN.bv_val = (char *)parentdn;
    888 	assertedParentDN.bv_len = strlen( parentdn );
    889 
    890 	if ( dnNormalize( 0, NULL, NULL, &assertedParentDN,
    891 		&normalizedAssertedParentDN, NULL ) != LDAP_SUCCESS )
    892 	{
    893 		return 0;
    894 	}
    895 
    896 	childDN.bv_val = (char *)childdn;
    897 	childDN.bv_len = strlen( childdn );
    898 
    899 	if ( dnNormalize( 0, NULL, NULL, &childDN,
    900 		&normalizedChildDN, NULL ) != LDAP_SUCCESS )
    901 	{
    902 		slapi_ch_free( (void **)&normalizedAssertedParentDN.bv_val );
    903 		return 0;
    904 	}
    905 
    906 	dnParent( &normalizedChildDN, &normalizedParentDN );
    907 
    908 	if ( dnMatch( &match, 0, slap_schema.si_syn_distinguishedName, NULL,
    909 		&normalizedParentDN, (void *)&normalizedAssertedParentDN ) != LDAP_SUCCESS )
    910 	{
    911 		match = -1;
    912 	}
    913 
    914 	slapi_ch_free( (void **)&normalizedAssertedParentDN.bv_val );
    915 	slapi_ch_free( (void **)&normalizedChildDN.bv_val );
    916 
    917 	return ( match == 0 );
    918 }
    919 
    920 /*
    921  * Returns DN of the parent entry, or NULL if the DN is
    922  * an empty string or NULL, or has no parent.
    923  */
    924 char *
    925 slapi_dn_parent( const char *_dn )
    926 {
    927 	struct berval	dn, prettyDN;
    928 	struct berval	parentDN;
    929 	char		*ret;
    930 
    931 	if ( _dn == NULL ) {
    932 		return NULL;
    933 	}
    934 
    935 	dn.bv_val = (char *)_dn;
    936 	dn.bv_len = strlen( _dn );
    937 
    938 	if ( dn.bv_len == 0 ) {
    939 		return NULL;
    940 	}
    941 
    942 	if ( dnPretty( NULL, &dn, &prettyDN, NULL ) != LDAP_SUCCESS ) {
    943 		return NULL;
    944 	}
    945 
    946 	dnParent( &prettyDN, &parentDN ); /* in-place */
    947 
    948 	if ( parentDN.bv_len == 0 ) {
    949 		slapi_ch_free_string( &prettyDN.bv_val );
    950 		return NULL;
    951 	}
    952 
    953 	ret = slapi_ch_strdup( parentDN.bv_val );
    954 	slapi_ch_free_string( &prettyDN.bv_val );
    955 
    956 	return ret;
    957 }
    958 
    959 int slapi_dn_isbesuffix( Slapi_PBlock *pb, char *ldn )
    960 {
    961 	struct berval	ndn;
    962 	Backend		*be;
    963 
    964 	if ( slapi_is_rootdse( ldn ) ) {
    965 		return 0;
    966 	}
    967 
    968 	/* according to spec should already be normalized */
    969 	ndn.bv_len = strlen( ldn );
    970 	ndn.bv_val = ldn;
    971 
    972 	be = select_backend( &pb->pb_op->o_req_ndn, 0 );
    973 	if ( be == NULL ) {
    974 		return 0;
    975 	}
    976 
    977 	return be_issuffix( be, &ndn );
    978 }
    979 
    980 /*
    981  * Returns DN of the parent entry; or NULL if the DN is
    982  * an empty string, if the DN has no parent, or if the
    983  * DN is the suffix of the backend database
    984  */
    985 char *slapi_dn_beparent( Slapi_PBlock *pb, const char *ldn )
    986 {
    987 	Backend 	*be;
    988 	struct berval	dn, prettyDN;
    989 	struct berval	normalizedDN, parentDN;
    990 	char		*parent = NULL;
    991 
    992 	if ( pb == NULL ) {
    993 		return NULL;
    994 	}
    995 
    996 	PBLOCK_ASSERT_OP( pb, 0 );
    997 
    998 	if ( slapi_is_rootdse( ldn ) ) {
    999 		return NULL;
   1000 	}
   1001 
   1002 	dn.bv_val = (char *)ldn;
   1003 	dn.bv_len = strlen( ldn );
   1004 
   1005 	if ( dnPrettyNormal( NULL, &dn, &prettyDN, &normalizedDN, NULL ) != LDAP_SUCCESS ) {
   1006 		return NULL;
   1007 	}
   1008 
   1009 	be = select_backend( &pb->pb_op->o_req_ndn, 0 );
   1010 
   1011 	if ( be == NULL || be_issuffix( be, &normalizedDN ) == 0 ) {
   1012 		dnParent( &prettyDN, &parentDN );
   1013 
   1014 		if ( parentDN.bv_len != 0 )
   1015 			parent = slapi_ch_strdup( parentDN.bv_val );
   1016 	}
   1017 
   1018 	slapi_ch_free_string( &prettyDN.bv_val );
   1019 	slapi_ch_free_string( &normalizedDN.bv_val );
   1020 
   1021 	return parent;
   1022 }
   1023 
   1024 char *
   1025 slapi_dn_ignore_case( char *dn )
   1026 {
   1027 	return slapi_dn_normalize_case( dn );
   1028 }
   1029 
   1030 char *
   1031 slapi_ch_malloc( unsigned long size )
   1032 {
   1033 	return ch_malloc( size );
   1034 }
   1035 
   1036 void
   1037 slapi_ch_free( void **ptr )
   1038 {
   1039 	if ( ptr == NULL || *ptr == NULL )
   1040 		return;
   1041 	ch_free( *ptr );
   1042 	*ptr = NULL;
   1043 }
   1044 
   1045 void
   1046 slapi_ch_free_string( char **ptr )
   1047 {
   1048 	slapi_ch_free( (void **)ptr );
   1049 }
   1050 
   1051 void
   1052 slapi_ch_array_free( char **arrayp )
   1053 {
   1054 	char **p;
   1055 
   1056 	if ( arrayp != NULL ) {
   1057 		for ( p = arrayp; *p != NULL; p++ ) {
   1058 			slapi_ch_free( (void **)p );
   1059 		}
   1060 		slapi_ch_free( (void **)&arrayp );
   1061 	}
   1062 }
   1063 
   1064 struct berval *
   1065 slapi_ch_bvdup(const struct berval *v)
   1066 {
   1067 	return ber_dupbv(NULL, (struct berval *)v);
   1068 }
   1069 
   1070 struct berval **
   1071 slapi_ch_bvecdup(const struct berval **v)
   1072 {
   1073 	int i;
   1074 	struct berval **rv;
   1075 
   1076 	if ( v == NULL ) {
   1077 		return NULL;
   1078 	}
   1079 
   1080 	for ( i = 0; v[i] != NULL; i++ )
   1081 		;
   1082 
   1083 	rv = (struct berval **) slapi_ch_malloc( (i + 1) * sizeof(struct berval *) );
   1084 
   1085 	for ( i = 0; v[i] != NULL; i++ ) {
   1086 		rv[i] = slapi_ch_bvdup( v[i] );
   1087 	}
   1088 	rv[i] = NULL;
   1089 
   1090 	return rv;
   1091 }
   1092 
   1093 char *
   1094 slapi_ch_calloc(
   1095 	unsigned long nelem,
   1096 	unsigned long size )
   1097 {
   1098 	return ch_calloc( nelem, size );
   1099 }
   1100 
   1101 char *
   1102 slapi_ch_realloc(
   1103 	char *block,
   1104 	unsigned long size )
   1105 {
   1106 	return ch_realloc( block, size );
   1107 }
   1108 
   1109 char *
   1110 slapi_ch_strdup( const char *s )
   1111 {
   1112 	return ch_strdup( s );
   1113 }
   1114 
   1115 size_t
   1116 slapi_ch_stlen( const char *s )
   1117 {
   1118 	return strlen( s );
   1119 }
   1120 
   1121 int
   1122 slapi_control_present(
   1123 	LDAPControl	**controls,
   1124 	char		*oid,
   1125 	struct berval	**val,
   1126 	int		*iscritical )
   1127 {
   1128 	int		i;
   1129 	int		rc = 0;
   1130 
   1131 	if ( val ) {
   1132 		*val = NULL;
   1133 	}
   1134 
   1135 	if ( iscritical ) {
   1136 		*iscritical = 0;
   1137 	}
   1138 
   1139 	for ( i = 0; controls != NULL && controls[i] != NULL; i++ ) {
   1140 		if ( strcmp( controls[i]->ldctl_oid, oid ) != 0 ) {
   1141 			continue;
   1142 		}
   1143 
   1144 		rc = 1;
   1145 		if ( controls[i]->ldctl_value.bv_len != 0 ) {
   1146 			if ( val ) {
   1147 				*val = &controls[i]->ldctl_value;
   1148 			}
   1149 		}
   1150 
   1151 		if ( iscritical ) {
   1152 			*iscritical = controls[i]->ldctl_iscritical;
   1153 		}
   1154 
   1155 		break;
   1156 	}
   1157 
   1158 	return rc;
   1159 }
   1160 
   1161 static void
   1162 slapControlMask2SlapiControlOp(slap_mask_t slap_mask,
   1163 	unsigned long *slapi_mask)
   1164 {
   1165 	*slapi_mask = SLAPI_OPERATION_NONE;
   1166 
   1167 	if ( slap_mask & SLAP_CTRL_ABANDON )
   1168 		*slapi_mask |= SLAPI_OPERATION_ABANDON;
   1169 
   1170 	if ( slap_mask & SLAP_CTRL_ADD )
   1171 		*slapi_mask |= SLAPI_OPERATION_ADD;
   1172 
   1173 	if ( slap_mask & SLAP_CTRL_BIND )
   1174 		*slapi_mask |= SLAPI_OPERATION_BIND;
   1175 
   1176 	if ( slap_mask & SLAP_CTRL_COMPARE )
   1177 		*slapi_mask |= SLAPI_OPERATION_COMPARE;
   1178 
   1179 	if ( slap_mask & SLAP_CTRL_DELETE )
   1180 		*slapi_mask |= SLAPI_OPERATION_DELETE;
   1181 
   1182 	if ( slap_mask & SLAP_CTRL_MODIFY )
   1183 		*slapi_mask |= SLAPI_OPERATION_MODIFY;
   1184 
   1185 	if ( slap_mask & SLAP_CTRL_RENAME )
   1186 		*slapi_mask |= SLAPI_OPERATION_MODDN;
   1187 
   1188 	if ( slap_mask & SLAP_CTRL_SEARCH )
   1189 		*slapi_mask |= SLAPI_OPERATION_SEARCH;
   1190 
   1191 	if ( slap_mask & SLAP_CTRL_UNBIND )
   1192 		*slapi_mask |= SLAPI_OPERATION_UNBIND;
   1193 }
   1194 
   1195 static void
   1196 slapiControlOp2SlapControlMask(unsigned long slapi_mask,
   1197 	slap_mask_t *slap_mask)
   1198 {
   1199 	*slap_mask = 0;
   1200 
   1201 	if ( slapi_mask & SLAPI_OPERATION_BIND )
   1202 		*slap_mask |= SLAP_CTRL_BIND;
   1203 
   1204 	if ( slapi_mask & SLAPI_OPERATION_UNBIND )
   1205 		*slap_mask |= SLAP_CTRL_UNBIND;
   1206 
   1207 	if ( slapi_mask & SLAPI_OPERATION_SEARCH )
   1208 		*slap_mask |= SLAP_CTRL_SEARCH;
   1209 
   1210 	if ( slapi_mask & SLAPI_OPERATION_MODIFY )
   1211 		*slap_mask |= SLAP_CTRL_MODIFY;
   1212 
   1213 	if ( slapi_mask & SLAPI_OPERATION_ADD )
   1214 		*slap_mask |= SLAP_CTRL_ADD;
   1215 
   1216 	if ( slapi_mask & SLAPI_OPERATION_DELETE )
   1217 		*slap_mask |= SLAP_CTRL_DELETE;
   1218 
   1219 	if ( slapi_mask & SLAPI_OPERATION_MODDN )
   1220 		*slap_mask |= SLAP_CTRL_RENAME;
   1221 
   1222 	if ( slapi_mask & SLAPI_OPERATION_COMPARE )
   1223 		*slap_mask |= SLAP_CTRL_COMPARE;
   1224 
   1225 	if ( slapi_mask & SLAPI_OPERATION_ABANDON )
   1226 		*slap_mask |= SLAP_CTRL_ABANDON;
   1227 
   1228 	*slap_mask |= SLAP_CTRL_GLOBAL;
   1229 }
   1230 
   1231 static int
   1232 slapi_int_parse_control(
   1233 	Operation *op,
   1234 	SlapReply *rs,
   1235 	LDAPControl *ctrl )
   1236 {
   1237 	/* Plugins must deal with controls themselves. */
   1238 
   1239 	return LDAP_SUCCESS;
   1240 }
   1241 
   1242 void
   1243 slapi_register_supported_control(
   1244 	char		*controloid,
   1245 	unsigned long	controlops )
   1246 {
   1247 	slap_mask_t controlmask;
   1248 
   1249 	slapiControlOp2SlapControlMask( controlops, &controlmask );
   1250 
   1251 	register_supported_control( controloid, controlmask, NULL, slapi_int_parse_control, NULL );
   1252 }
   1253 
   1254 int
   1255 slapi_get_supported_controls(
   1256 	char		***ctrloidsp,
   1257 	unsigned long	**ctrlopsp )
   1258 {
   1259 	int i, rc;
   1260 
   1261 	rc = get_supported_controls( ctrloidsp, (slap_mask_t **)ctrlopsp );
   1262 	if ( rc != LDAP_SUCCESS ) {
   1263 		return rc;
   1264 	}
   1265 
   1266 	for ( i = 0; (*ctrloidsp)[i] != NULL; i++ ) {
   1267 		/* In place, naughty. */
   1268 		slapControlMask2SlapiControlOp( (*ctrlopsp)[i], &((*ctrlopsp)[i]) );
   1269 	}
   1270 
   1271 	return LDAP_SUCCESS;
   1272 }
   1273 
   1274 LDAPControl *
   1275 slapi_dup_control( LDAPControl *ctrl )
   1276 {
   1277 	LDAPControl *ret;
   1278 
   1279 	ret = (LDAPControl *)slapi_ch_malloc( sizeof(*ret) );
   1280 	ret->ldctl_oid = slapi_ch_strdup( ctrl->ldctl_oid );
   1281 	ber_dupbv( &ret->ldctl_value, &ctrl->ldctl_value );
   1282 	ret->ldctl_iscritical = ctrl->ldctl_iscritical;
   1283 
   1284 	return ret;
   1285 }
   1286 
   1287 void
   1288 slapi_register_supported_saslmechanism( char *mechanism )
   1289 {
   1290 	/* FIXME -- can not add saslmechanism to OpenLDAP dynamically */
   1291 	slapi_log_error( SLAPI_LOG_FATAL, "slapi_register_supported_saslmechanism",
   1292 			"OpenLDAP does not support dynamic registration of SASL mechanisms\n" );
   1293 }
   1294 
   1295 char **
   1296 slapi_get_supported_saslmechanisms( void )
   1297 {
   1298 	/* FIXME -- can not get the saslmechanism without a connection. */
   1299 	slapi_log_error( SLAPI_LOG_FATAL, "slapi_get_supported_saslmechanisms",
   1300 			"can not get the SASL mechanism list "
   1301 			"without a connection\n" );
   1302 	return NULL;
   1303 }
   1304 
   1305 char **
   1306 slapi_get_supported_extended_ops( void )
   1307 {
   1308 	int		i, j, k;
   1309 	char		**ppExtOpOID = NULL;
   1310 	int		numExtOps = 0;
   1311 
   1312 	for ( i = 0; get_supported_extop( i ) != NULL; i++ ) {
   1313 		;
   1314 	}
   1315 
   1316 	for ( j = 0; slapi_int_get_supported_extop( j ) != NULL; j++ ) {
   1317 		;
   1318 	}
   1319 
   1320 	numExtOps = i + j;
   1321 	if ( numExtOps == 0 ) {
   1322 		return NULL;
   1323 	}
   1324 
   1325 	ppExtOpOID = (char **)slapi_ch_malloc( (numExtOps + 1) * sizeof(char *) );
   1326 	for ( k = 0; k < i; k++ ) {
   1327 		struct berval	*bv;
   1328 
   1329 		bv = get_supported_extop( k );
   1330 		assert( bv != NULL );
   1331 
   1332 		ppExtOpOID[ k ] = bv->bv_val;
   1333 	}
   1334 
   1335 	for ( ; k < j; k++ ) {
   1336 		struct berval	*bv;
   1337 
   1338 		bv = slapi_int_get_supported_extop( k );
   1339 		assert( bv != NULL );
   1340 
   1341 		ppExtOpOID[ i + k ] = bv->bv_val;
   1342 	}
   1343 	ppExtOpOID[ i + k ] = NULL;
   1344 
   1345 	return ppExtOpOID;
   1346 }
   1347 
   1348 void
   1349 slapi_send_ldap_result(
   1350 	Slapi_PBlock	*pb,
   1351 	int		err,
   1352 	char		*matched,
   1353 	char		*text,
   1354 	int		nentries,
   1355 	struct berval	**urls )
   1356 {
   1357 	SlapReply	*rs;
   1358 
   1359 	PBLOCK_ASSERT_OP( pb, 0 );
   1360 
   1361 	rs = pb->pb_rs;
   1362 
   1363 	rs->sr_err = err;
   1364 	rs->sr_matched = matched;
   1365 	rs->sr_text = text;
   1366 	rs->sr_ref = NULL;
   1367 
   1368 	if ( err == LDAP_SASL_BIND_IN_PROGRESS ) {
   1369 		send_ldap_sasl( pb->pb_op, rs );
   1370 	} else if ( rs->sr_rspoid != NULL ) {
   1371 		send_ldap_extended( pb->pb_op, rs );
   1372 	} else {
   1373 		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
   1374 			rs->sr_nentries = nentries;
   1375 		if ( urls != NULL )
   1376 			bvptr2obj( urls, &rs->sr_ref, NULL );
   1377 
   1378 		send_ldap_result( pb->pb_op, rs );
   1379 
   1380 		if ( urls != NULL )
   1381 			slapi_ch_free( (void **)&rs->sr_ref );
   1382 	}
   1383 }
   1384 
   1385 int
   1386 slapi_send_ldap_search_entry(
   1387 	Slapi_PBlock	*pb,
   1388 	Slapi_Entry	*e,
   1389 	LDAPControl	**ectrls,
   1390 	char		**attrs,
   1391 	int		attrsonly )
   1392 {
   1393 	SlapReply		rs = { REP_SEARCH };
   1394 	int			i = 0, j = 0;
   1395 	AttributeName		*an = NULL;
   1396 	const char		*text;
   1397 	int			rc;
   1398 
   1399 	assert( pb->pb_op != NULL );
   1400 
   1401 	if ( attrs != NULL ) {
   1402 		for ( i = 0; attrs[ i ] != NULL; i++ ) {
   1403 			; /* empty */
   1404 		}
   1405 	}
   1406 
   1407 	if ( i ) {
   1408 		an = (AttributeName *) slapi_ch_calloc( i + 1, sizeof(AttributeName) );
   1409 		for ( i = 0; attrs[i] != NULL; i++ ) {
   1410 			an[j].an_name.bv_val = attrs[i];
   1411 			an[j].an_name.bv_len = strlen( attrs[i] );
   1412 			an[j].an_desc = NULL;
   1413 			if ( slap_bv2ad( &an[j].an_name, &an[j].an_desc, &text ) == LDAP_SUCCESS) {
   1414 				j++;
   1415 			}
   1416 		}
   1417 		an[j].an_name.bv_len = 0;
   1418 		an[j].an_name.bv_val = NULL;
   1419 	}
   1420 
   1421 	rs.sr_err = LDAP_SUCCESS;
   1422 	rs.sr_matched = NULL;
   1423 	rs.sr_text = NULL;
   1424 	rs.sr_ref = NULL;
   1425 	rs.sr_ctrls = ectrls;
   1426 	rs.sr_attrs = an;
   1427 	rs.sr_operational_attrs = NULL;
   1428 	rs.sr_entry = e;
   1429 	rs.sr_v2ref = NULL;
   1430 	rs.sr_flags = 0;
   1431 
   1432 	rc = send_search_entry( pb->pb_op, &rs );
   1433 
   1434 	slapi_ch_free( (void **)&an );
   1435 
   1436 	return rc;
   1437 }
   1438 
   1439 int
   1440 slapi_send_ldap_search_reference(
   1441 	Slapi_PBlock	*pb,
   1442 	Slapi_Entry	*e,
   1443 	struct berval	**references,
   1444 	LDAPControl	**ectrls,
   1445 	struct berval	**v2refs
   1446 	)
   1447 {
   1448 	SlapReply	rs = { REP_SEARCHREF };
   1449 	int		rc;
   1450 
   1451 	rs.sr_err = LDAP_SUCCESS;
   1452 	rs.sr_matched = NULL;
   1453 	rs.sr_text = NULL;
   1454 
   1455 	rc = bvptr2obj( references, &rs.sr_ref, NULL );
   1456 	if ( rc != LDAP_SUCCESS ) {
   1457 		return rc;
   1458 	}
   1459 
   1460 	rs.sr_ctrls = ectrls;
   1461 	rs.sr_attrs = NULL;
   1462 	rs.sr_operational_attrs = NULL;
   1463 	rs.sr_entry = e;
   1464 
   1465 	if ( v2refs != NULL ) {
   1466 		rc = bvptr2obj( v2refs, &rs.sr_v2ref, NULL );
   1467 		if ( rc != LDAP_SUCCESS ) {
   1468 			slapi_ch_free( (void **)&rs.sr_ref );
   1469 			return rc;
   1470 		}
   1471 	} else {
   1472 		rs.sr_v2ref = NULL;
   1473 	}
   1474 
   1475 	rc = send_search_reference( pb->pb_op, &rs );
   1476 
   1477 	slapi_ch_free( (void **)&rs.sr_ref );
   1478 	slapi_ch_free( (void **)&rs.sr_v2ref );
   1479 
   1480 	return rc;
   1481 }
   1482 
   1483 Slapi_Filter *
   1484 slapi_str2filter( char *str )
   1485 {
   1486 	return str2filter( str );
   1487 }
   1488 
   1489 void
   1490 slapi_filter_free(
   1491 	Slapi_Filter	*f,
   1492 	int		recurse )
   1493 {
   1494 	filter_free( f );
   1495 }
   1496 
   1497 Slapi_Filter *
   1498 slapi_filter_dup( Slapi_Filter *filter )
   1499 {
   1500 	return filter_dup( filter, NULL );
   1501 }
   1502 
   1503 int
   1504 slapi_filter_get_choice( Slapi_Filter *f )
   1505 {
   1506 	int		rc;
   1507 
   1508 	if ( f != NULL ) {
   1509 		rc = f->f_choice;
   1510 	} else {
   1511 		rc = 0;
   1512 	}
   1513 
   1514 	return rc;
   1515 }
   1516 
   1517 int
   1518 slapi_filter_get_ava(
   1519 	Slapi_Filter	*f,
   1520 	char		**type,
   1521 	struct berval	**bval )
   1522 {
   1523 	int		ftype;
   1524 	int		rc = LDAP_SUCCESS;
   1525 
   1526 	assert( type != NULL );
   1527 	assert( bval != NULL );
   1528 
   1529 	*type = NULL;
   1530 	*bval = NULL;
   1531 
   1532 	ftype = f->f_choice;
   1533 	if ( ftype == LDAP_FILTER_EQUALITY
   1534 			|| ftype ==  LDAP_FILTER_GE
   1535 			|| ftype == LDAP_FILTER_LE
   1536 			|| ftype == LDAP_FILTER_APPROX ) {
   1537 		/*
   1538 		 * According to the SLAPI Reference Manual these are
   1539 		 * not duplicated.
   1540 		 */
   1541 		*type = f->f_un.f_un_ava->aa_desc->ad_cname.bv_val;
   1542 		*bval = &f->f_un.f_un_ava->aa_value;
   1543 	} else { /* filter type not supported */
   1544 		rc = -1;
   1545 	}
   1546 
   1547 	return rc;
   1548 }
   1549 
   1550 Slapi_Filter *
   1551 slapi_filter_list_first( Slapi_Filter *f )
   1552 {
   1553 	int		ftype;
   1554 
   1555 	if ( f == NULL ) {
   1556 		return NULL;
   1557 	}
   1558 
   1559 	ftype = f->f_choice;
   1560 	if ( ftype == LDAP_FILTER_AND
   1561 			|| ftype == LDAP_FILTER_OR
   1562 			|| ftype == LDAP_FILTER_NOT ) {
   1563 		return (Slapi_Filter *)f->f_list;
   1564 	} else {
   1565 		return NULL;
   1566 	}
   1567 }
   1568 
   1569 Slapi_Filter *
   1570 slapi_filter_list_next(
   1571 	Slapi_Filter	*f,
   1572 	Slapi_Filter	*fprev )
   1573 {
   1574 	int		ftype;
   1575 
   1576 	if ( f == NULL ) {
   1577 		return NULL;
   1578 	}
   1579 
   1580 	ftype = f->f_choice;
   1581 	if ( ftype == LDAP_FILTER_AND
   1582 			|| ftype == LDAP_FILTER_OR
   1583 			|| ftype == LDAP_FILTER_NOT )
   1584 	{
   1585 		return fprev->f_next;
   1586 	}
   1587 
   1588 	return NULL;
   1589 }
   1590 
   1591 int
   1592 slapi_filter_get_attribute_type( Slapi_Filter *f, char **type )
   1593 {
   1594 	if ( f == NULL ) {
   1595 		return -1;
   1596 	}
   1597 
   1598 	switch ( f->f_choice ) {
   1599 	case LDAP_FILTER_GE:
   1600 	case LDAP_FILTER_LE:
   1601 	case LDAP_FILTER_EQUALITY:
   1602 	case LDAP_FILTER_APPROX:
   1603 		*type = f->f_av_desc->ad_cname.bv_val;
   1604 		break;
   1605 	case LDAP_FILTER_SUBSTRINGS:
   1606 		*type = f->f_sub_desc->ad_cname.bv_val;
   1607 		break;
   1608 	case LDAP_FILTER_PRESENT:
   1609 		*type = f->f_desc->ad_cname.bv_val;
   1610 		break;
   1611 	case LDAP_FILTER_EXT:
   1612 		*type = f->f_mr_desc->ad_cname.bv_val;
   1613 		break;
   1614 	default:
   1615 		/* Complex filters need not apply. */
   1616 		*type = NULL;
   1617 		return -1;
   1618 	}
   1619 
   1620 	return 0;
   1621 }
   1622 
   1623 int
   1624 slapi_x_filter_set_attribute_type( Slapi_Filter *f, const char *type )
   1625 {
   1626 	AttributeDescription **adp, *ad = NULL;
   1627 	const char *text;
   1628 	int rc;
   1629 
   1630 	if ( f == NULL ) {
   1631 		return -1;
   1632 	}
   1633 
   1634 	switch ( f->f_choice ) {
   1635 	case LDAP_FILTER_GE:
   1636 	case LDAP_FILTER_LE:
   1637 	case LDAP_FILTER_EQUALITY:
   1638 	case LDAP_FILTER_APPROX:
   1639 		adp = &f->f_av_desc;
   1640 		break;
   1641 	case LDAP_FILTER_SUBSTRINGS:
   1642 		adp = &f->f_sub_desc;
   1643 		break;
   1644 	case LDAP_FILTER_PRESENT:
   1645 		adp = &f->f_desc;
   1646 		break;
   1647 	case LDAP_FILTER_EXT:
   1648 		adp = &f->f_mr_desc;
   1649 		break;
   1650 	default:
   1651 		/* Complex filters need not apply. */
   1652 		return -1;
   1653 	}
   1654 
   1655 	rc = slap_str2ad( type, &ad, &text );
   1656 	if ( rc == LDAP_SUCCESS )
   1657 		*adp = ad;
   1658 
   1659 	return ( rc == LDAP_SUCCESS ) ? 0 : -1;
   1660 }
   1661 
   1662 int
   1663 slapi_filter_get_subfilt( Slapi_Filter *f, char **type, char **initial,
   1664 	char ***any, char **final )
   1665 {
   1666 	int i;
   1667 
   1668 	if ( f->f_choice != LDAP_FILTER_SUBSTRINGS ) {
   1669 		return -1;
   1670 	}
   1671 
   1672 	/*
   1673 	 * The caller shouldn't free but we can't return an
   1674 	 * array of char *s from an array of bervals without
   1675 	 * allocating memory, so we may as well be consistent.
   1676 	 * XXX
   1677 	 */
   1678 	*type = f->f_sub_desc->ad_cname.bv_val;
   1679 	*initial = f->f_sub_initial.bv_val ? slapi_ch_strdup(f->f_sub_initial.bv_val) : NULL;
   1680 	if ( f->f_sub_any != NULL ) {
   1681 		for ( i = 0; f->f_sub_any[i].bv_val != NULL; i++ )
   1682 			;
   1683 		*any = (char **)slapi_ch_malloc( (i + 1) * sizeof(char *) );
   1684 		for ( i = 0; f->f_sub_any[i].bv_val != NULL; i++ ) {
   1685 			(*any)[i] = slapi_ch_strdup(f->f_sub_any[i].bv_val);
   1686 		}
   1687 		(*any)[i] = NULL;
   1688 	} else {
   1689 		*any = NULL;
   1690 	}
   1691 	*final = f->f_sub_final.bv_val ? slapi_ch_strdup(f->f_sub_final.bv_val) : NULL;
   1692 
   1693 	return 0;
   1694 }
   1695 
   1696 Slapi_Filter *
   1697 slapi_filter_join( int ftype, Slapi_Filter *f1, Slapi_Filter *f2 )
   1698 {
   1699 	Slapi_Filter *f = NULL;
   1700 
   1701 	if ( ftype == LDAP_FILTER_AND ||
   1702 	     ftype == LDAP_FILTER_OR ||
   1703 	     ftype == LDAP_FILTER_NOT )
   1704 	{
   1705 		f = (Slapi_Filter *)slapi_ch_malloc( sizeof(*f) );
   1706 		f->f_choice = ftype;
   1707 		f->f_list = f1;
   1708 		f->f_list->f_next = f2;
   1709 		f->f_next = NULL;
   1710 	}
   1711 
   1712 	return f;
   1713 }
   1714 
   1715 int
   1716 slapi_x_filter_append( int ftype,
   1717 	Slapi_Filter **pContainingFilter, /* NULL on first call */
   1718 	Slapi_Filter **pNextFilter,
   1719 	Slapi_Filter *filterToAppend )
   1720 {
   1721 	if ( ftype == LDAP_FILTER_AND ||
   1722 	     ftype == LDAP_FILTER_OR ||
   1723 	     ftype == LDAP_FILTER_NOT )
   1724 	{
   1725 		if ( *pContainingFilter == NULL ) {
   1726 			*pContainingFilter = (Slapi_Filter *)slapi_ch_malloc( sizeof(Slapi_Filter) );
   1727 			(*pContainingFilter)->f_choice = ftype;
   1728 			(*pContainingFilter)->f_list = filterToAppend;
   1729 			(*pContainingFilter)->f_next = NULL;
   1730 		} else {
   1731 			if ( (*pContainingFilter)->f_choice != ftype ) {
   1732 				/* Sanity check */
   1733 				return -1;
   1734 			}
   1735 			(*pNextFilter)->f_next = filterToAppend;
   1736 		}
   1737 		*pNextFilter = filterToAppend;
   1738 
   1739 		return 0;
   1740 	}
   1741 	return -1;
   1742 }
   1743 
   1744 int
   1745 slapi_filter_test( Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Filter *f,
   1746 	int verify_access )
   1747 {
   1748 	Operation *op;
   1749 	int rc;
   1750 
   1751 	if ( f == NULL ) {
   1752 		/* spec says return zero if no filter. */
   1753 		return 0;
   1754 	}
   1755 
   1756 	if ( verify_access ) {
   1757 		op = pb->pb_op;
   1758 		if ( op == NULL )
   1759 			return LDAP_PARAM_ERROR;
   1760 	} else {
   1761 		op = NULL;
   1762 	}
   1763 
   1764 	/*
   1765 	 * According to acl.c it is safe to call test_filter() with
   1766 	 * NULL arguments...
   1767 	 */
   1768 	rc = test_filter( op, e, f );
   1769 	switch (rc) {
   1770 	case LDAP_COMPARE_TRUE:
   1771 		rc = 0;
   1772 		break;
   1773 	case LDAP_COMPARE_FALSE:
   1774 		break;
   1775 	case SLAPD_COMPARE_UNDEFINED:
   1776 		rc = LDAP_OTHER;
   1777 		break;
   1778 	case LDAP_PROTOCOL_ERROR:
   1779 		/* filter type unknown: spec says return -1 */
   1780 		rc = -1;
   1781 		break;
   1782 	}
   1783 
   1784 	return rc;
   1785 }
   1786 
   1787 int
   1788 slapi_filter_test_simple( Slapi_Entry *e, Slapi_Filter *f)
   1789 {
   1790 	return slapi_filter_test( NULL, e, f, 0 );
   1791 }
   1792 
   1793 int
   1794 slapi_filter_apply( Slapi_Filter *f, FILTER_APPLY_FN fn, void *arg, int *error_code )
   1795 {
   1796 	switch ( f->f_choice ) {
   1797 	case LDAP_FILTER_AND:
   1798 	case LDAP_FILTER_NOT:
   1799 	case LDAP_FILTER_OR: {
   1800 		int rc;
   1801 
   1802 		/*
   1803 		 * FIXME: altering f; should we use a temporary?
   1804 		 */
   1805 		for ( f = f->f_list; f != NULL; f = f->f_next ) {
   1806 			rc = slapi_filter_apply( f, fn, arg, error_code );
   1807 			if ( rc != 0 ) {
   1808 				return rc;
   1809 			}
   1810 			if ( *error_code == SLAPI_FILTER_SCAN_NOMORE ) {
   1811 				break;
   1812 			}
   1813 		}
   1814 		break;
   1815 	}
   1816 	case LDAP_FILTER_EQUALITY:
   1817 	case LDAP_FILTER_SUBSTRINGS:
   1818 	case LDAP_FILTER_GE:
   1819 	case LDAP_FILTER_LE:
   1820 	case LDAP_FILTER_PRESENT:
   1821 	case LDAP_FILTER_APPROX:
   1822 	case LDAP_FILTER_EXT:
   1823 		*error_code = fn( f, arg );
   1824 		break;
   1825 	default:
   1826 		*error_code = SLAPI_FILTER_UNKNOWN_FILTER_TYPE;
   1827 	}
   1828 
   1829 	if ( *error_code == SLAPI_FILTER_SCAN_NOMORE ||
   1830 	     *error_code == SLAPI_FILTER_SCAN_CONTINUE ) {
   1831 		return 0;
   1832 	}
   1833 
   1834 	return -1;
   1835 }
   1836 
   1837 int
   1838 slapi_pw_find(
   1839 	struct berval	**vals,
   1840 	struct berval	*v )
   1841 {
   1842 	int i;
   1843 
   1844 	if( ( vals == NULL ) || ( v == NULL ) )
   1845 		return 1;
   1846 
   1847 	for ( i = 0; vals[i] != NULL; i++ ) {
   1848 		if ( !lutil_passwd( vals[i], v, NULL, NULL ) )
   1849 			return 0;
   1850 	}
   1851 
   1852 	return 1;
   1853 }
   1854 
   1855 /* Get connected client IP address.
   1856  *
   1857  * The user must free the returned client IP after its use.
   1858  * Compatible with IBM Tivoli call.
   1859  *
   1860  * Errors:
   1861  * * LDAP_PARAM_ERROR - If the pb parameter is null.
   1862  * * LDAP_OPERATIONS_ERROR - If the API encounters error processing the request.
   1863  * * LDAP_NO_MEMORY - Failed to allocate required memory.
   1864  */
   1865 int
   1866 slapi_get_client_ip(Slapi_PBlock *pb, char **clientIP)
   1867 {
   1868 	char *s = NULL;
   1869 
   1870 	if(pb == NULL || pb->pb_conn == NULL) return(LDAP_PARAM_ERROR);
   1871 	if((s = (char *) slapi_ch_malloc(pb->pb_conn->c_peer_name.bv_len + 1)) == NULL) {
   1872 		return(LDAP_NO_MEMORY);
   1873 	}
   1874 
   1875 	memcpy(s, pb->pb_conn->c_peer_name.bv_val, pb->pb_conn->c_peer_name.bv_len);
   1876 
   1877 	s[pb->pb_conn->c_peer_name.bv_len] = 0;
   1878 
   1879 	*clientIP = s;
   1880 
   1881 	return(LDAP_SUCCESS);
   1882 }
   1883 
   1884 /* Free previously allocated client IP address. */
   1885 void
   1886 slapi_free_client_ip(char **clientIP)
   1887 {
   1888 	slapi_ch_free((void **) clientIP);
   1889 }
   1890 
   1891 #define MAX_HOSTNAME 512
   1892 
   1893 char *
   1894 slapi_get_hostname( void )
   1895 {
   1896 	char		*hn = NULL;
   1897 	static int	been_here = 0;
   1898 	static char	*static_hn = NULL;
   1899 
   1900 	ldap_pvt_thread_mutex_lock( &slapi_hn_mutex );
   1901 	if ( !been_here ) {
   1902 		static_hn = (char *)slapi_ch_malloc( MAX_HOSTNAME );
   1903 		if ( static_hn == NULL) {
   1904 			slapi_log_error( SLAPI_LOG_FATAL, "slapi_get_hostname",
   1905 					"Cannot allocate memory for hostname\n" );
   1906 			static_hn = NULL;
   1907 			ldap_pvt_thread_mutex_unlock( &slapi_hn_mutex );
   1908 
   1909 			return hn;
   1910 
   1911 		} else {
   1912 			if ( gethostname( static_hn, MAX_HOSTNAME ) != 0 ) {
   1913 				slapi_log_error( SLAPI_LOG_FATAL,
   1914 						"SLAPI",
   1915 						"can't get hostname\n" );
   1916 				slapi_ch_free( (void **)&static_hn );
   1917 				static_hn = NULL;
   1918 				ldap_pvt_thread_mutex_unlock( &slapi_hn_mutex );
   1919 
   1920 				return hn;
   1921 
   1922 			} else {
   1923 				been_here = 1;
   1924 			}
   1925 		}
   1926 	}
   1927 	ldap_pvt_thread_mutex_unlock( &slapi_hn_mutex );
   1928 
   1929 	hn = ch_strdup( static_hn );
   1930 
   1931 	return hn;
   1932 }
   1933 
   1934 /*
   1935  * FIXME: this should go in an appropriate header ...
   1936  */
   1937 extern int slapi_int_log_error( int level, char *subsystem, char *fmt, va_list arglist );
   1938 
   1939 int
   1940 slapi_log_error(
   1941 	int		severity,
   1942 	char		*subsystem,
   1943 	char		*fmt,
   1944 	... )
   1945 {
   1946 	int		rc = LDAP_SUCCESS;
   1947 	va_list		arglist;
   1948 
   1949 	va_start( arglist, fmt );
   1950 	rc = slapi_int_log_error( severity, subsystem, fmt, arglist );
   1951 	va_end( arglist );
   1952 
   1953 	return rc;
   1954 }
   1955 
   1956 
   1957 unsigned long
   1958 slapi_timer_current_time( void )
   1959 {
   1960 	static int	first_time = 1;
   1961 #if !defined (_WIN32)
   1962 	struct timeval	now;
   1963 	unsigned long	ret;
   1964 
   1965 	ldap_pvt_thread_mutex_lock( &slapi_time_mutex );
   1966 	if (first_time) {
   1967 		first_time = 0;
   1968 		gettimeofday( &base_time, NULL );
   1969 	}
   1970 	gettimeofday( &now, NULL );
   1971 	ret = ( now.tv_sec  - base_time.tv_sec ) * 1000000 +
   1972 			(now.tv_usec - base_time.tv_usec);
   1973 	ldap_pvt_thread_mutex_unlock( &slapi_time_mutex );
   1974 
   1975 	return ret;
   1976 
   1977 	/*
   1978 	 * Ain't it better?
   1979 	return (slap_get_time() - starttime) * 1000000;
   1980 	 */
   1981 #else /* _WIN32 */
   1982 	LARGE_INTEGER now;
   1983 	static LARGE_INTEGER base_time, performance_freq;
   1984 	static int performance_counter_present;
   1985 
   1986 	if ( first_time ) {
   1987 		first_time = 0;
   1988 		performance_counter_present = QueryPerformanceCounter( &base_time );
   1989 		QueryPerformanceFrequency( &performance_freq );
   1990 	}
   1991 
   1992 	if ( !performance_counter_present )
   1993 	     return 0;
   1994 
   1995 	QueryPerformanceCounter( &now );
   1996 	return (1000000*(now.QuadPart-base_time.QuadPart))/performance_freq.QuadPart;
   1997 #endif /* _WIN32 */
   1998 }
   1999 
   2000 /*
   2001  * FIXME ?
   2002  */
   2003 unsigned long
   2004 slapi_timer_get_time( char *label )
   2005 {
   2006 	unsigned long start = slapi_timer_current_time();
   2007 	printf("%10ld %10d usec %s\n", start, 0, label);
   2008 	return start;
   2009 }
   2010 
   2011 /*
   2012  * FIXME ?
   2013  */
   2014 void
   2015 slapi_timer_elapsed_time(
   2016 	char *label,
   2017 	unsigned long start )
   2018 {
   2019 	unsigned long stop = slapi_timer_current_time();
   2020 	printf ("%10ld %10ld usec %s\n", stop, stop - start, label);
   2021 }
   2022 
   2023 void
   2024 slapi_free_search_results_internal( Slapi_PBlock *pb )
   2025 {
   2026 	Slapi_Entry	**entries;
   2027 	int		k = 0, nEnt = 0;
   2028 
   2029 	slapi_pblock_get( pb, SLAPI_NENTRIES, &nEnt );
   2030 	slapi_pblock_get( pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries );
   2031 	if ( nEnt == 0 || entries == NULL ) {
   2032 		return;
   2033 	}
   2034 
   2035 	for ( k = 0; k < nEnt; k++ ) {
   2036 		slapi_entry_free( entries[k] );
   2037 		entries[k] = NULL;
   2038 	}
   2039 
   2040 	slapi_ch_free( (void **)&entries );
   2041 }
   2042 
   2043 int slapi_is_connection_ssl( Slapi_PBlock *pb, int *isSSL )
   2044 {
   2045 	if ( pb == NULL )
   2046 		return LDAP_PARAM_ERROR;
   2047 
   2048 	if ( pb->pb_conn == NULL )
   2049 		return LDAP_PARAM_ERROR;
   2050 
   2051 #ifdef HAVE_TLS
   2052 	*isSSL = pb->pb_conn->c_is_tls;
   2053 #else
   2054 	*isSSL = 0;
   2055 #endif
   2056 
   2057 	return LDAP_SUCCESS;
   2058 }
   2059 
   2060 /*
   2061  * DS 5.x compatibility API follow
   2062  */
   2063 
   2064 int slapi_attr_get_flags( const Slapi_Attr *attr, unsigned long *flags )
   2065 {
   2066 	AttributeType *at;
   2067 
   2068 	if ( attr == NULL )
   2069 		return LDAP_PARAM_ERROR;
   2070 
   2071 	at = attr->a_desc->ad_type;
   2072 
   2073 	*flags = SLAPI_ATTR_FLAG_STD_ATTR;
   2074 
   2075 	if ( is_at_single_value( at ) )
   2076 		*flags |= SLAPI_ATTR_FLAG_SINGLE;
   2077 	if ( is_at_operational( at ) )
   2078 		*flags |= SLAPI_ATTR_FLAG_OPATTR;
   2079 	if ( is_at_obsolete( at ) )
   2080 		*flags |= SLAPI_ATTR_FLAG_OBSOLETE;
   2081 	if ( is_at_collective( at ) )
   2082 		*flags |= SLAPI_ATTR_FLAG_COLLECTIVE;
   2083 	if ( is_at_no_user_mod( at ) )
   2084 		*flags |= SLAPI_ATTR_FLAG_NOUSERMOD;
   2085 
   2086 	return LDAP_SUCCESS;
   2087 }
   2088 
   2089 int slapi_attr_flag_is_set( const Slapi_Attr *attr, unsigned long flag )
   2090 {
   2091 	unsigned long flags;
   2092 
   2093 	if ( slapi_attr_get_flags( attr, &flags ) != 0 )
   2094 		return 0;
   2095 	return (flags & flag) ? 1 : 0;
   2096 }
   2097 
   2098 Slapi_Attr *slapi_attr_new( void )
   2099 {
   2100 	Attribute *ad;
   2101 
   2102 	ad = (Attribute  *)slapi_ch_calloc( 1, sizeof(*ad) );
   2103 
   2104 	return ad;
   2105 }
   2106 
   2107 Slapi_Attr *slapi_attr_init( Slapi_Attr *a, const char *type )
   2108 {
   2109 	const char *text;
   2110 	AttributeDescription *ad = NULL;
   2111 
   2112 	if( slap_str2ad( type, &ad, &text ) != LDAP_SUCCESS ) {
   2113 		return NULL;
   2114 	}
   2115 
   2116 	a->a_desc = ad;
   2117 	a->a_vals = NULL;
   2118 	a->a_nvals = NULL;
   2119 	a->a_next = NULL;
   2120 	a->a_flags = 0;
   2121 
   2122 	return a;
   2123 }
   2124 
   2125 void slapi_attr_free( Slapi_Attr **a )
   2126 {
   2127 	attr_free( *a );
   2128 	*a = NULL;
   2129 }
   2130 
   2131 Slapi_Attr *slapi_attr_dup( const Slapi_Attr *attr )
   2132 {
   2133 	return attr_dup( (Slapi_Attr *)attr );
   2134 }
   2135 
   2136 int slapi_attr_add_value( Slapi_Attr *a, const Slapi_Value *v )
   2137 {
   2138 	struct berval nval;
   2139 	struct berval *nvalp;
   2140 	int rc;
   2141 	AttributeDescription *desc = a->a_desc;
   2142 
   2143 	if ( desc->ad_type->sat_equality &&
   2144 	     desc->ad_type->sat_equality->smr_normalize ) {
   2145 		rc = (*desc->ad_type->sat_equality->smr_normalize)(
   2146 			SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
   2147 			desc->ad_type->sat_syntax,
   2148 			desc->ad_type->sat_equality,
   2149 			(Slapi_Value *)v, &nval, NULL );
   2150 		if ( rc != LDAP_SUCCESS ) {
   2151 			return rc;
   2152 		}
   2153 		nvalp = &nval;
   2154 	} else {
   2155 		nvalp = NULL;
   2156 	}
   2157 
   2158 	rc = attr_valadd( a, (Slapi_Value *)v, nvalp, 1 );
   2159 
   2160 	if ( nvalp != NULL ) {
   2161 		slapi_ch_free_string( &nval.bv_val );
   2162 	}
   2163 
   2164 	return rc;
   2165 }
   2166 
   2167 int slapi_attr_type2plugin( const char *type, void **pi )
   2168 {
   2169 	*pi = NULL;
   2170 
   2171 	return LDAP_OTHER;
   2172 }
   2173 
   2174 int slapi_attr_get_type( const Slapi_Attr *attr, char **type )
   2175 {
   2176 	if ( attr == NULL ) {
   2177 		return LDAP_PARAM_ERROR;
   2178 	}
   2179 
   2180 	*type = attr->a_desc->ad_cname.bv_val;
   2181 
   2182 	return LDAP_SUCCESS;
   2183 }
   2184 
   2185 int slapi_attr_get_oid_copy( const Slapi_Attr *attr, char **oidp )
   2186 {
   2187 	if ( attr == NULL ) {
   2188 		return LDAP_PARAM_ERROR;
   2189 	}
   2190 	*oidp = attr->a_desc->ad_type->sat_oid;
   2191 
   2192 	return LDAP_SUCCESS;
   2193 }
   2194 
   2195 int slapi_attr_value_cmp( const Slapi_Attr *a, const struct berval *v1, const struct berval *v2 )
   2196 {
   2197 	MatchingRule *mr;
   2198 	int ret;
   2199 	int rc;
   2200 	const char *text;
   2201 
   2202 	mr = a->a_desc->ad_type->sat_equality;
   2203 	rc = value_match( &ret, a->a_desc, mr,
   2204 			SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
   2205 		(struct berval *)v1, (void *)v2, &text );
   2206 	if ( rc != LDAP_SUCCESS )
   2207 		return -1;
   2208 
   2209 	return ( ret == 0 ) ? 0 : -1;
   2210 }
   2211 
   2212 int slapi_attr_value_find( const Slapi_Attr *a, struct berval *v )
   2213 {
   2214 	int rc;
   2215 
   2216 	if ( a ->a_vals == NULL ) {
   2217 		return -1;
   2218 	}
   2219 	rc = attr_valfind( (Attribute *)a, SLAP_MR_VALUE_OF_ASSERTION_SYNTAX, v,
   2220 		NULL, NULL );
   2221 	return rc == 0 ? 0 : -1;
   2222 }
   2223 
   2224 int slapi_attr_type_cmp( const char *t1, const char *t2, int opt )
   2225 {
   2226 	AttributeDescription *a1 = NULL;
   2227 	AttributeDescription *a2 = NULL;
   2228 	const char *text;
   2229 	int ret;
   2230 
   2231 	if ( slap_str2ad( t1, &a1, &text ) != LDAP_SUCCESS ) {
   2232 		return -1;
   2233 	}
   2234 
   2235 	if ( slap_str2ad( t2, &a2, &text ) != LDAP_SUCCESS ) {
   2236 		return 1;
   2237 	}
   2238 
   2239 #define ad_base_cmp(l,r) (((l)->ad_type->sat_cname.bv_len < (r)->ad_type->sat_cname.bv_len) \
   2240 	? -1 : (((l)->ad_type->sat_cname.bv_len > (r)->ad_type->sat_cname.bv_len) \
   2241 		? 1 : strcasecmp((l)->ad_type->sat_cname.bv_val, (r)->ad_type->sat_cname.bv_val )))
   2242 
   2243 	switch ( opt ) {
   2244 	case SLAPI_TYPE_CMP_EXACT:
   2245 		ret = ad_cmp( a1, a2 );
   2246 		break;
   2247 	case SLAPI_TYPE_CMP_BASE:
   2248 		ret = ad_base_cmp( a1, a2 );
   2249 		break;
   2250 	case SLAPI_TYPE_CMP_SUBTYPE:
   2251 		ret = is_ad_subtype( a2, a2 );
   2252 		break;
   2253 	default:
   2254 		ret = -1;
   2255 		break;
   2256 	}
   2257 
   2258 	return ret;
   2259 }
   2260 
   2261 int slapi_attr_types_equivalent( const char *t1, const char *t2 )
   2262 {
   2263 	return ( slapi_attr_type_cmp( t1, t2, SLAPI_TYPE_CMP_EXACT ) == 0 );
   2264 }
   2265 
   2266 int slapi_attr_first_value( Slapi_Attr *a, Slapi_Value **v )
   2267 {
   2268 	return slapi_valueset_first_value( &a->a_vals, v );
   2269 }
   2270 
   2271 int slapi_attr_next_value( Slapi_Attr *a, int hint, Slapi_Value **v )
   2272 {
   2273 	return slapi_valueset_next_value( &a->a_vals, hint, v );
   2274 }
   2275 
   2276 int slapi_attr_get_numvalues( const Slapi_Attr *a, int *numValues )
   2277 {
   2278 	*numValues = slapi_valueset_count( &a->a_vals );
   2279 
   2280 	return 0;
   2281 }
   2282 
   2283 int slapi_attr_get_valueset( const Slapi_Attr *a, Slapi_ValueSet **vs )
   2284 {
   2285 	*vs = &((Slapi_Attr *)a)->a_vals;
   2286 
   2287 	return 0;
   2288 }
   2289 
   2290 int slapi_attr_get_bervals_copy( Slapi_Attr *a, struct berval ***vals )
   2291 {
   2292 	return slapi_attr_get_values( a, vals );
   2293 }
   2294 
   2295 char *slapi_attr_syntax_normalize( const char *s )
   2296 {
   2297 	AttributeDescription *ad = NULL;
   2298 	const char *text;
   2299 
   2300 	if ( slap_str2ad( s, &ad, &text ) != LDAP_SUCCESS ) {
   2301 		return NULL;
   2302 	}
   2303 
   2304 	return ad->ad_cname.bv_val;
   2305 }
   2306 
   2307 Slapi_Value *slapi_value_new( void )
   2308 {
   2309 	struct berval *bv;
   2310 
   2311 	bv = (struct berval *)slapi_ch_malloc( sizeof(*bv) );
   2312 
   2313 	return bv;
   2314 }
   2315 
   2316 Slapi_Value *slapi_value_new_berval(const struct berval *bval)
   2317 {
   2318 	return ber_dupbv( NULL, (struct berval *)bval );
   2319 }
   2320 
   2321 Slapi_Value *slapi_value_new_value(const Slapi_Value *v)
   2322 {
   2323 	return slapi_value_new_berval( v );
   2324 }
   2325 
   2326 Slapi_Value *slapi_value_new_string(const char *s)
   2327 {
   2328 	struct berval bv;
   2329 
   2330 	bv.bv_val = (char *)s;
   2331 	bv.bv_len = strlen( s );
   2332 
   2333 	return slapi_value_new_berval( &bv );
   2334 }
   2335 
   2336 Slapi_Value *slapi_value_init(Slapi_Value *val)
   2337 {
   2338 	val->bv_val = NULL;
   2339 	val->bv_len = 0;
   2340 
   2341 	return val;
   2342 }
   2343 
   2344 Slapi_Value *slapi_value_init_berval(Slapi_Value *v, struct berval *bval)
   2345 {
   2346 	return ber_dupbv( v, bval );
   2347 }
   2348 
   2349 Slapi_Value *slapi_value_init_string(Slapi_Value *v, const char *s)
   2350 {
   2351 	v->bv_val = slapi_ch_strdup( s );
   2352 	v->bv_len = strlen( s );
   2353 
   2354 	return v;
   2355 }
   2356 
   2357 Slapi_Value *slapi_value_dup(const Slapi_Value *v)
   2358 {
   2359 	return slapi_value_new_value( v );
   2360 }
   2361 
   2362 void slapi_value_free(Slapi_Value **value)
   2363 {
   2364 	if ( value == NULL ) {
   2365 		return;
   2366 	}
   2367 
   2368 	if ( (*value) != NULL ) {
   2369 		slapi_ch_free( (void **)&(*value)->bv_val );
   2370 		slapi_ch_free( (void **)value );
   2371 	}
   2372 }
   2373 
   2374 const struct berval *slapi_value_get_berval( const Slapi_Value *value )
   2375 {
   2376 	return value;
   2377 }
   2378 
   2379 Slapi_Value *slapi_value_set_berval( Slapi_Value *value, const struct berval *bval )
   2380 {
   2381 	if ( value == NULL ) {
   2382 		return NULL;
   2383 	}
   2384 	if ( value->bv_val != NULL ) {
   2385 		slapi_ch_free( (void **)&value->bv_val );
   2386 	}
   2387 	slapi_value_init_berval( value, (struct berval *)bval );
   2388 
   2389 	return value;
   2390 }
   2391 
   2392 Slapi_Value *slapi_value_set_value( Slapi_Value *value, const Slapi_Value *vfrom)
   2393 {
   2394 	if ( value == NULL ) {
   2395 		return NULL;
   2396 	}
   2397 	return slapi_value_set_berval( value, vfrom );
   2398 }
   2399 
   2400 Slapi_Value *slapi_value_set( Slapi_Value *value, void *val, unsigned long len)
   2401 {
   2402 	if ( value == NULL ) {
   2403 		return NULL;
   2404 	}
   2405 	if ( value->bv_val != NULL ) {
   2406 		slapi_ch_free( (void **)&value->bv_val );
   2407 	}
   2408 	value->bv_val = slapi_ch_malloc( len );
   2409 	value->bv_len = len;
   2410 	AC_MEMCPY( value->bv_val, val, len );
   2411 
   2412 	return value;
   2413 }
   2414 
   2415 int slapi_value_set_string(Slapi_Value *value, const char *strVal)
   2416 {
   2417 	if ( value == NULL ) {
   2418 		return -1;
   2419 	}
   2420 	slapi_value_set( value, (void *)strVal, strlen( strVal ) );
   2421 	return 0;
   2422 }
   2423 
   2424 int slapi_value_set_int(Slapi_Value *value, int intVal)
   2425 {
   2426 	char buf[64];
   2427 
   2428 	snprintf( buf, sizeof( buf ), "%d", intVal );
   2429 
   2430 	return slapi_value_set_string( value, buf );
   2431 }
   2432 
   2433 const char *slapi_value_get_string(const Slapi_Value *value)
   2434 {
   2435 	if ( value == NULL ) return NULL;
   2436 	if ( value->bv_val == NULL ) return NULL;
   2437 	if ( !checkBVString( value ) ) return NULL;
   2438 
   2439 	return value->bv_val;
   2440 }
   2441 
   2442 int slapi_value_get_int(const Slapi_Value *value)
   2443 {
   2444 	if ( value == NULL ) return 0;
   2445 	if ( value->bv_val == NULL ) return 0;
   2446 	if ( !checkBVString( value ) ) return 0;
   2447 
   2448 	return (int)strtol( value->bv_val, NULL, 10 );
   2449 }
   2450 
   2451 unsigned int slapi_value_get_uint(const Slapi_Value *value)
   2452 {
   2453 	if ( value == NULL ) return 0;
   2454 	if ( value->bv_val == NULL ) return 0;
   2455 	if ( !checkBVString( value ) ) return 0;
   2456 
   2457 	return (unsigned int)strtoul( value->bv_val, NULL, 10 );
   2458 }
   2459 
   2460 long slapi_value_get_long(const Slapi_Value *value)
   2461 {
   2462 	if ( value == NULL ) return 0;
   2463 	if ( value->bv_val == NULL ) return 0;
   2464 	if ( !checkBVString( value ) ) return 0;
   2465 
   2466 	return strtol( value->bv_val, NULL, 10 );
   2467 }
   2468 
   2469 unsigned long slapi_value_get_ulong(const Slapi_Value *value)
   2470 {
   2471 	if ( value == NULL ) return 0;
   2472 	if ( value->bv_val == NULL ) return 0;
   2473 	if ( !checkBVString( value ) ) return 0;
   2474 
   2475 	return strtoul( value->bv_val, NULL, 10 );
   2476 }
   2477 
   2478 size_t slapi_value_get_length(const Slapi_Value *value)
   2479 {
   2480 	if ( value == NULL )
   2481 		return 0;
   2482 
   2483 	return (size_t) value->bv_len;
   2484 }
   2485 
   2486 int slapi_value_compare(const Slapi_Attr *a, const Slapi_Value *v1, const Slapi_Value *v2)
   2487 {
   2488 	return slapi_attr_value_cmp( a, v1, v2 );
   2489 }
   2490 
   2491 /* A ValueSet is a container for a BerVarray. */
   2492 Slapi_ValueSet *slapi_valueset_new( void )
   2493 {
   2494 	Slapi_ValueSet *vs;
   2495 
   2496 	vs = (Slapi_ValueSet *)slapi_ch_malloc( sizeof( *vs ) );
   2497 	*vs = NULL;
   2498 
   2499 	return vs;
   2500 }
   2501 
   2502 void slapi_valueset_free(Slapi_ValueSet *vs)
   2503 {
   2504 	if ( vs != NULL ) {
   2505 		BerVarray vp = *vs;
   2506 
   2507 		ber_bvarray_free( vp );
   2508 		vp = NULL;
   2509 
   2510 		slapi_ch_free( (void **)&vp );
   2511 	}
   2512 }
   2513 
   2514 void slapi_valueset_init(Slapi_ValueSet *vs)
   2515 {
   2516 	if ( vs != NULL && *vs == NULL ) {
   2517 		*vs = (Slapi_ValueSet)slapi_ch_calloc( 1, sizeof(struct berval) );
   2518 		(*vs)->bv_val = NULL;
   2519 		(*vs)->bv_len = 0;
   2520 	}
   2521 }
   2522 
   2523 void slapi_valueset_done(Slapi_ValueSet *vs)
   2524 {
   2525 	BerVarray vp;
   2526 
   2527 	if ( vs == NULL )
   2528 		return;
   2529 
   2530 	for ( vp = *vs; vp->bv_val != NULL; vp++ ) {
   2531 		vp->bv_len = 0;
   2532 		slapi_ch_free( (void **)&vp->bv_val );
   2533 	}
   2534 	/* but don't free *vs or vs */
   2535 }
   2536 
   2537 void slapi_valueset_add_value(Slapi_ValueSet *vs, const Slapi_Value *addval)
   2538 {
   2539 	struct berval bv;
   2540 
   2541 	ber_dupbv( &bv, (Slapi_Value *)addval );
   2542 	ber_bvarray_add( vs, &bv );
   2543 }
   2544 
   2545 int slapi_valueset_first_value( Slapi_ValueSet *vs, Slapi_Value **v )
   2546 {
   2547 	return slapi_valueset_next_value( vs, 0, v );
   2548 }
   2549 
   2550 int slapi_valueset_next_value( Slapi_ValueSet *vs, int index, Slapi_Value **v)
   2551 {
   2552 	int i;
   2553 	BerVarray vp;
   2554 
   2555 	if ( vs == NULL )
   2556 		return -1;
   2557 
   2558 	vp = *vs;
   2559 
   2560 	for ( i = 0; vp[i].bv_val != NULL; i++ ) {
   2561 		if ( i == index ) {
   2562 			*v = &vp[i];
   2563 			return index + 1;
   2564 		}
   2565 	}
   2566 
   2567 	return -1;
   2568 }
   2569 
   2570 int slapi_valueset_count( const Slapi_ValueSet *vs )
   2571 {
   2572 	int i;
   2573 	BerVarray vp;
   2574 
   2575 	if ( vs == NULL )
   2576 		return 0;
   2577 
   2578 	vp = *vs;
   2579 
   2580 	if ( vp == NULL )
   2581 		return 0;
   2582 
   2583 	for ( i = 0; vp[i].bv_val != NULL; i++ )
   2584 		;
   2585 
   2586 	return i;
   2587 
   2588 }
   2589 
   2590 void slapi_valueset_set_valueset(Slapi_ValueSet *vs1, const Slapi_ValueSet *vs2)
   2591 {
   2592 	BerVarray vp;
   2593 
   2594 	for ( vp = *vs2; vp->bv_val != NULL; vp++ ) {
   2595 		slapi_valueset_add_value( vs1, vp );
   2596 	}
   2597 }
   2598 
   2599 int slapi_access_allowed( Slapi_PBlock *pb, Slapi_Entry *e, char *attr,
   2600 	struct berval *val, int access )
   2601 {
   2602 	int rc;
   2603 	slap_access_t slap_access;
   2604 	AttributeDescription *ad = NULL;
   2605 	const char *text;
   2606 
   2607 	rc = slap_str2ad( attr, &ad, &text );
   2608 	if ( rc != LDAP_SUCCESS ) {
   2609 		return rc;
   2610 	}
   2611 
   2612 	/*
   2613 	 * Whilst the SLAPI access types are arranged as a bitmask, the
   2614 	 * documentation indicates that they are to be used separately.
   2615 	 */
   2616 	switch ( access & SLAPI_ACL_ALL ) {
   2617 	case SLAPI_ACL_COMPARE:
   2618 		slap_access = ACL_COMPARE;
   2619 		break;
   2620 	case SLAPI_ACL_SEARCH:
   2621 		slap_access = ACL_SEARCH;
   2622 		break;
   2623 	case SLAPI_ACL_READ:
   2624 		slap_access = ACL_READ;
   2625 		break;
   2626 	case SLAPI_ACL_WRITE:
   2627 		slap_access = ACL_WRITE;
   2628 		break;
   2629 	case SLAPI_ACL_DELETE:
   2630 		slap_access = ACL_WDEL;
   2631 		break;
   2632 	case SLAPI_ACL_ADD:
   2633 		slap_access = ACL_WADD;
   2634 		break;
   2635 	case SLAPI_ACL_SELF:  /* not documented */
   2636 	case SLAPI_ACL_PROXY: /* not documented */
   2637 	default:
   2638 		return LDAP_INSUFFICIENT_ACCESS;
   2639 		break;
   2640 	}
   2641 
   2642 	assert( pb->pb_op != NULL );
   2643 
   2644 	if ( access_allowed( pb->pb_op, e, ad, val, slap_access, NULL ) ) {
   2645 		return LDAP_SUCCESS;
   2646 	}
   2647 
   2648 	return LDAP_INSUFFICIENT_ACCESS;
   2649 }
   2650 
   2651 int slapi_acl_check_mods(Slapi_PBlock *pb, Slapi_Entry *e, LDAPMod **mods, char **errbuf)
   2652 {
   2653 	int rc = LDAP_SUCCESS;
   2654 	Modifications *ml;
   2655 
   2656 	if ( pb == NULL || pb->pb_op == NULL )
   2657 		return LDAP_PARAM_ERROR;
   2658 
   2659 	ml = slapi_int_ldapmods2modifications( pb->pb_op, mods );
   2660 	if ( ml == NULL ) {
   2661 		return LDAP_OTHER;
   2662 	}
   2663 
   2664 	if ( rc == LDAP_SUCCESS ) {
   2665 		rc = acl_check_modlist( pb->pb_op, e, ml ) ? LDAP_SUCCESS : LDAP_INSUFFICIENT_ACCESS;
   2666 	}
   2667 
   2668 	slap_mods_free( ml, 1 );
   2669 
   2670 	return rc;
   2671 }
   2672 
   2673 /*
   2674  * Synthesise an LDAPMod array from a Modifications list to pass
   2675  * to SLAPI.
   2676  */
   2677 LDAPMod **slapi_int_modifications2ldapmods( Modifications *modlist )
   2678 {
   2679 	Modifications *ml;
   2680 	LDAPMod **mods, *modp;
   2681 	int i, j;
   2682 
   2683 	for( i = 0, ml = modlist; ml != NULL; i++, ml = ml->sml_next )
   2684 		;
   2685 
   2686 	mods = (LDAPMod **)slapi_ch_malloc( (i + 1) * sizeof(LDAPMod *) );
   2687 
   2688 	for( i = 0, ml = modlist; ml != NULL; ml = ml->sml_next ) {
   2689 		mods[i] = (LDAPMod *)slapi_ch_malloc( sizeof(LDAPMod) );
   2690 		modp = mods[i];
   2691 		modp->mod_op = ml->sml_op | LDAP_MOD_BVALUES;
   2692 		if ( BER_BVISNULL( &ml->sml_type ) ) {
   2693 			/* may happen for internally generated mods */
   2694 			assert( ml->sml_desc != NULL );
   2695 			modp->mod_type = slapi_ch_strdup( ml->sml_desc->ad_cname.bv_val );
   2696 		} else {
   2697 			modp->mod_type = slapi_ch_strdup( ml->sml_type.bv_val );
   2698 		}
   2699 
   2700 		if ( ml->sml_values != NULL ) {
   2701 			for( j = 0; ml->sml_values[j].bv_val != NULL; j++ )
   2702 				;
   2703 			modp->mod_bvalues = (struct berval **)slapi_ch_malloc( (j + 1) *
   2704 				sizeof(struct berval *) );
   2705 			for( j = 0; ml->sml_values[j].bv_val != NULL; j++ ) {
   2706 				modp->mod_bvalues[j] = (struct berval *)slapi_ch_malloc(
   2707 						sizeof(struct berval) );
   2708 				ber_dupbv( modp->mod_bvalues[j], &ml->sml_values[j] );
   2709 			}
   2710 			modp->mod_bvalues[j] = NULL;
   2711 		} else {
   2712 			modp->mod_bvalues = NULL;
   2713 		}
   2714 		i++;
   2715 	}
   2716 
   2717 	mods[i] = NULL;
   2718 
   2719 	return mods;
   2720 }
   2721 
   2722 /*
   2723  * Convert a potentially modified array of LDAPMods back to a
   2724  * Modification list. Unfortunately the values need to be
   2725  * duplicated because slap_mods_check() will try to free them
   2726  * before prettying (and we can't easily get out of calling
   2727  * slap_mods_check() because we need normalized values).
   2728  */
   2729 Modifications *slapi_int_ldapmods2modifications ( Operation *op, LDAPMod **mods )
   2730 {
   2731 	Modifications *modlist = NULL, **modtail;
   2732 	LDAPMod **modp;
   2733 	char textbuf[SLAP_TEXT_BUFLEN];
   2734 	const char *text;
   2735 
   2736 	if ( mods == NULL ) {
   2737 		return NULL;
   2738 	}
   2739 
   2740 	modtail = &modlist;
   2741 
   2742 	for ( modp = mods; *modp != NULL; modp++ ) {
   2743 		Modifications *mod;
   2744 		LDAPMod *lmod = *modp;
   2745 		int i;
   2746 		const char *text;
   2747 		AttributeDescription *ad = NULL;
   2748 
   2749 		if ( slap_str2ad( lmod->mod_type, &ad, &text ) != LDAP_SUCCESS ) {
   2750 			continue;
   2751 		}
   2752 
   2753 		mod = (Modifications *) slapi_ch_malloc( sizeof(Modifications) );
   2754 		mod->sml_op = lmod->mod_op & ~(LDAP_MOD_BVALUES);
   2755 		mod->sml_flags = 0;
   2756 		mod->sml_type = ad->ad_cname;
   2757 		mod->sml_desc = ad;
   2758 		mod->sml_next = NULL;
   2759 
   2760 		i = 0;
   2761 		if ( lmod->mod_op & LDAP_MOD_BVALUES ) {
   2762 			if ( lmod->mod_bvalues != NULL ) {
   2763 				while ( lmod->mod_bvalues[i] != NULL )
   2764 					i++;
   2765 			}
   2766 		} else {
   2767 			if ( lmod->mod_values != NULL ) {
   2768 				while ( lmod->mod_values[i] != NULL )
   2769 					i++;
   2770 			}
   2771 		}
   2772 		mod->sml_numvals = i;
   2773 
   2774 		if ( i == 0 ) {
   2775 			mod->sml_values = NULL;
   2776 		} else {
   2777 			mod->sml_values = (BerVarray) slapi_ch_malloc( (i + 1) * sizeof(struct berval) );
   2778 
   2779 			/* NB: This implicitly trusts a plugin to return valid modifications. */
   2780 			if ( lmod->mod_op & LDAP_MOD_BVALUES ) {
   2781 				for ( i = 0; lmod->mod_bvalues[i] != NULL; i++ ) {
   2782 					ber_dupbv( &mod->sml_values[i], lmod->mod_bvalues[i] );
   2783 				}
   2784 			} else {
   2785 				for ( i = 0; lmod->mod_values[i] != NULL; i++ ) {
   2786 					mod->sml_values[i].bv_val = slapi_ch_strdup( lmod->mod_values[i] );
   2787 					mod->sml_values[i].bv_len = strlen( lmod->mod_values[i] );
   2788 				}
   2789 			}
   2790 			mod->sml_values[i].bv_val = NULL;
   2791 			mod->sml_values[i].bv_len = 0;
   2792 		}
   2793 		mod->sml_nvalues = NULL;
   2794 
   2795 		*modtail = mod;
   2796 		modtail = &mod->sml_next;
   2797 	}
   2798 
   2799 	if ( slap_mods_check( op, modlist, &text, textbuf, sizeof( textbuf ), NULL ) != LDAP_SUCCESS ) {
   2800 		slap_mods_free( modlist, 1 );
   2801 		modlist = NULL;
   2802 	}
   2803 
   2804 	return modlist;
   2805 }
   2806 
   2807 /*
   2808  * Sun ONE DS 5.x computed attribute support. Computed attributes
   2809  * allow for dynamically generated operational attributes, a very
   2810  * useful thing indeed.
   2811  */
   2812 
   2813 /*
   2814  * For some reason Sun don't use the normal plugin mechanism
   2815  * registration path to register an "evaluator" function (an
   2816  * "evaluator" is responsible for adding computed attributes;
   2817  * the nomenclature is somewhat confusing).
   2818  *
   2819  * As such slapi_compute_add_evaluator() registers the
   2820  * function directly.
   2821  */
   2822 int slapi_compute_add_evaluator(slapi_compute_callback_t function)
   2823 {
   2824 	Slapi_PBlock *pPlugin = NULL;
   2825 	int rc;
   2826 	int type = SLAPI_PLUGIN_OBJECT;
   2827 
   2828 	pPlugin = slapi_pblock_new();
   2829 	if ( pPlugin == NULL ) {
   2830 		rc = LDAP_NO_MEMORY;
   2831 		goto done;
   2832 	}
   2833 
   2834 	rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_TYPE, (void *)&type );
   2835 	if ( rc != LDAP_SUCCESS ) {
   2836 		goto done;
   2837 	}
   2838 
   2839 	rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_COMPUTE_EVALUATOR_FN, (void *)function );
   2840 	if ( rc != LDAP_SUCCESS ) {
   2841 		goto done;
   2842 	}
   2843 
   2844 	rc = slapi_int_register_plugin( frontendDB, pPlugin );
   2845 	if ( rc != 0 ) {
   2846 		rc = LDAP_OTHER;
   2847 		goto done;
   2848 	}
   2849 
   2850 done:
   2851 	if ( rc != LDAP_SUCCESS ) {
   2852 		if ( pPlugin != NULL ) {
   2853 			slapi_pblock_destroy( pPlugin );
   2854 		}
   2855 		return -1;
   2856 	}
   2857 
   2858 	return 0;
   2859 }
   2860 
   2861 /*
   2862  * See notes above regarding slapi_compute_add_evaluator().
   2863  */
   2864 int slapi_compute_add_search_rewriter(slapi_search_rewrite_callback_t function)
   2865 {
   2866 	Slapi_PBlock *pPlugin = NULL;
   2867 	int rc;
   2868 	int type = SLAPI_PLUGIN_OBJECT;
   2869 
   2870 	pPlugin = slapi_pblock_new();
   2871 	if ( pPlugin == NULL ) {
   2872 		rc = LDAP_NO_MEMORY;
   2873 		goto done;
   2874 	}
   2875 
   2876 	rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_TYPE, (void *)&type );
   2877 	if ( rc != LDAP_SUCCESS ) {
   2878 		goto done;
   2879 	}
   2880 
   2881 	rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_COMPUTE_SEARCH_REWRITER_FN, (void *)function );
   2882 	if ( rc != LDAP_SUCCESS ) {
   2883 		goto done;
   2884 	}
   2885 
   2886 	rc = slapi_int_register_plugin( frontendDB, pPlugin );
   2887 	if ( rc != 0 ) {
   2888 		rc = LDAP_OTHER;
   2889 		goto done;
   2890 	}
   2891 
   2892 done:
   2893 	if ( rc != LDAP_SUCCESS ) {
   2894 		if ( pPlugin != NULL ) {
   2895 			slapi_pblock_destroy( pPlugin );
   2896 		}
   2897 		return -1;
   2898 	}
   2899 
   2900 	return 0;
   2901 }
   2902 
   2903 /*
   2904  * Call compute evaluators
   2905  */
   2906 int compute_evaluator(computed_attr_context *c, char *type, Slapi_Entry *e, slapi_compute_output_t outputfn)
   2907 {
   2908 	int rc = 0;
   2909 	slapi_compute_callback_t *pGetPlugin, *tmpPlugin;
   2910 
   2911 	rc = slapi_int_get_plugins( frontendDB, SLAPI_PLUGIN_COMPUTE_EVALUATOR_FN, (SLAPI_FUNC **)&tmpPlugin );
   2912 	if ( rc != LDAP_SUCCESS || tmpPlugin == NULL ) {
   2913 		/* Nothing to do; front-end should ignore. */
   2914 		return 0;
   2915 	}
   2916 
   2917 	for ( pGetPlugin = tmpPlugin; *pGetPlugin != NULL; pGetPlugin++ ) {
   2918 		/*
   2919 		 * -1: no attribute matched requested type
   2920 		 *  0: one attribute matched
   2921 		 * >0: error happened
   2922 		 */
   2923 		rc = (*pGetPlugin)( c, type, e, outputfn );
   2924 		if ( rc > 0 ) {
   2925 			break;
   2926 		}
   2927 	}
   2928 
   2929 	slapi_ch_free( (void **)&tmpPlugin );
   2930 
   2931 	return rc;
   2932 }
   2933 
   2934 int
   2935 compute_rewrite_search_filter( Slapi_PBlock *pb )
   2936 {
   2937 	if ( pb == NULL || pb->pb_op == NULL )
   2938 		return LDAP_PARAM_ERROR;
   2939 
   2940 	return slapi_int_call_plugins( pb->pb_op->o_bd, SLAPI_PLUGIN_COMPUTE_SEARCH_REWRITER_FN, pb );
   2941 }
   2942 
   2943 /*
   2944  * New API to provide the plugin with access to the search
   2945  * pblock. Have informed Sun DS team.
   2946  */
   2947 int
   2948 slapi_x_compute_get_pblock(computed_attr_context *c, Slapi_PBlock **pb)
   2949 {
   2950 	if ( c == NULL )
   2951 		return -1;
   2952 
   2953 	if ( c->cac_pb == NULL )
   2954 		return -1;
   2955 
   2956 	*pb = c->cac_pb;
   2957 
   2958 	return 0;
   2959 }
   2960 
   2961 Slapi_Mutex *slapi_new_mutex( void )
   2962 {
   2963 	Slapi_Mutex *m;
   2964 
   2965 	m = (Slapi_Mutex *)slapi_ch_malloc( sizeof(*m) );
   2966 	if ( ldap_pvt_thread_mutex_init( &m->mutex ) != 0 ) {
   2967 		slapi_ch_free( (void **)&m );
   2968 		return NULL;
   2969 	}
   2970 
   2971 	return m;
   2972 }
   2973 
   2974 void slapi_destroy_mutex( Slapi_Mutex *mutex )
   2975 {
   2976 	if ( mutex != NULL ) {
   2977 		ldap_pvt_thread_mutex_destroy( &mutex->mutex );
   2978 		slapi_ch_free( (void **)&mutex);
   2979 	}
   2980 }
   2981 
   2982 void slapi_lock_mutex( Slapi_Mutex *mutex )
   2983 {
   2984 	ldap_pvt_thread_mutex_lock( &mutex->mutex );
   2985 }
   2986 
   2987 int slapi_unlock_mutex( Slapi_Mutex *mutex )
   2988 {
   2989 	return ldap_pvt_thread_mutex_unlock( &mutex->mutex );
   2990 }
   2991 
   2992 Slapi_CondVar *slapi_new_condvar( Slapi_Mutex *mutex )
   2993 {
   2994 	Slapi_CondVar *cv;
   2995 
   2996 	if ( mutex == NULL ) {
   2997 		return NULL;
   2998 	}
   2999 
   3000 	cv = (Slapi_CondVar *)slapi_ch_malloc( sizeof(*cv) );
   3001 	if ( ldap_pvt_thread_cond_init( &cv->cond ) != 0 ) {
   3002 		slapi_ch_free( (void **)&cv );
   3003 		return NULL;
   3004 	}
   3005 
   3006 	cv->mutex = mutex->mutex;
   3007 
   3008 	return cv;
   3009 }
   3010 
   3011 void slapi_destroy_condvar( Slapi_CondVar *cvar )
   3012 {
   3013 	if ( cvar != NULL ) {
   3014 		ldap_pvt_thread_cond_destroy( &cvar->cond );
   3015 		slapi_ch_free( (void **)&cvar );
   3016 	}
   3017 }
   3018 
   3019 int slapi_wait_condvar( Slapi_CondVar *cvar, struct timeval *timeout )
   3020 {
   3021 	if ( cvar == NULL ) {
   3022 		return -1;
   3023 	}
   3024 
   3025 	return ldap_pvt_thread_cond_wait( &cvar->cond, &cvar->mutex );
   3026 }
   3027 
   3028 int slapi_notify_condvar( Slapi_CondVar *cvar, int notify_all )
   3029 {
   3030 	if ( cvar == NULL ) {
   3031 		return -1;
   3032 	}
   3033 
   3034 	if ( notify_all ) {
   3035 		return ldap_pvt_thread_cond_broadcast( &cvar->cond );
   3036 	}
   3037 
   3038 	return ldap_pvt_thread_cond_signal( &cvar->cond );
   3039 }
   3040 
   3041 int slapi_int_access_allowed( Operation *op,
   3042 	Entry *entry,
   3043 	AttributeDescription *desc,
   3044 	struct berval *val,
   3045 	slap_access_t access,
   3046 	AccessControlState *state )
   3047 {
   3048 	int rc, slap_access = 0;
   3049 	slapi_acl_callback_t *pGetPlugin, *tmpPlugin;
   3050 	Slapi_PBlock *pb;
   3051 
   3052 	pb = SLAPI_OPERATION_PBLOCK( op );
   3053 	if ( pb == NULL ) {
   3054 		/* internal operation */
   3055 		return 1;
   3056 	}
   3057 
   3058 	switch ( access ) {
   3059 	case ACL_COMPARE:
   3060                 slap_access |= SLAPI_ACL_COMPARE;
   3061 		break;
   3062 	case ACL_SEARCH:
   3063 		slap_access |= SLAPI_ACL_SEARCH;
   3064 		break;
   3065 	case ACL_READ:
   3066 		slap_access |= SLAPI_ACL_READ;
   3067 		break;
   3068 	case ACL_WRITE:
   3069 		slap_access |= SLAPI_ACL_WRITE;
   3070 		break;
   3071 	case ACL_WDEL:
   3072 		slap_access |= SLAPI_ACL_DELETE;
   3073 		break;
   3074 	case ACL_WADD:
   3075 		slap_access |= SLAPI_ACL_ADD;
   3076 		break;
   3077 	default:
   3078 		break;
   3079         }
   3080 
   3081 	rc = slapi_int_get_plugins( frontendDB, SLAPI_PLUGIN_ACL_ALLOW_ACCESS, (SLAPI_FUNC **)&tmpPlugin );
   3082 	if ( rc != LDAP_SUCCESS || tmpPlugin == NULL ) {
   3083 		/* nothing to do; allowed access */
   3084 		return 1;
   3085 	}
   3086 
   3087 	rc = 1; /* default allow policy */
   3088 
   3089 	for ( pGetPlugin = tmpPlugin; *pGetPlugin != NULL; pGetPlugin++ ) {
   3090 		/*
   3091 		 * 0	access denied
   3092 		 * 1	access granted
   3093 		 */
   3094 		rc = (*pGetPlugin)( pb, entry, desc->ad_cname.bv_val,
   3095 				    val, slap_access, (void *)state );
   3096 		if ( rc == 0 ) {
   3097 			break;
   3098 		}
   3099 	}
   3100 
   3101 	slapi_ch_free( (void **)&tmpPlugin );
   3102 
   3103 	return rc;
   3104 }
   3105 
   3106 /*
   3107  * There is no documentation for this.
   3108  */
   3109 int slapi_rdn2typeval( char *rdn, char **type, struct berval *bv )
   3110 {
   3111 	LDAPRDN lrdn;
   3112 	LDAPAVA *ava;
   3113 	int rc;
   3114 	char *p;
   3115 
   3116 	*type = NULL;
   3117 
   3118 	bv->bv_len = 0;
   3119 	bv->bv_val = NULL;
   3120 
   3121 	rc = ldap_str2rdn( rdn, &lrdn, &p, LDAP_DN_FORMAT_LDAPV3 );
   3122 	if ( rc != LDAP_SUCCESS ) {
   3123 		return -1;
   3124 	}
   3125 
   3126 	if ( lrdn[1] != NULL ) {
   3127 		return -1; /* not single valued */
   3128 	}
   3129 
   3130 	ava = lrdn[0];
   3131 
   3132 	*type = slapi_ch_strdup( ava->la_attr.bv_val );
   3133 	ber_dupbv( bv, &ava->la_value );
   3134 
   3135 	ldap_rdnfree(lrdn);
   3136 
   3137 	return 0;
   3138 }
   3139 
   3140 char *slapi_dn_plus_rdn( const char *dn, const char *rdn )
   3141 {
   3142 	struct berval new_dn, parent_dn, newrdn;
   3143 
   3144 	new_dn.bv_val = NULL;
   3145 
   3146 	parent_dn.bv_val = (char *)dn;
   3147 	parent_dn.bv_len = strlen( dn );
   3148 
   3149 	newrdn.bv_val = (char *)rdn;
   3150 	newrdn.bv_len = strlen( rdn );
   3151 
   3152 	build_new_dn( &new_dn, &parent_dn, &newrdn, NULL );
   3153 
   3154 	return new_dn.bv_val;
   3155 }
   3156 
   3157 int slapi_entry_schema_check( Slapi_PBlock *pb, Slapi_Entry *e )
   3158 {
   3159 	Backend *be_orig;
   3160 	const char *text;
   3161 	char textbuf[SLAP_TEXT_BUFLEN] = { '\0' };
   3162 	size_t textlen = sizeof textbuf;
   3163 	int rc = LDAP_SUCCESS;
   3164 
   3165 	PBLOCK_ASSERT_OP( pb, 0 );
   3166 
   3167 	be_orig = pb->pb_op->o_bd;
   3168 
   3169 	pb->pb_op->o_bd = select_backend( &e->e_nname, 0 );
   3170 	if ( pb->pb_op->o_bd != NULL ) {
   3171 		rc = entry_schema_check( pb->pb_op, e, NULL, 0, 0, NULL,
   3172 			&text, textbuf, textlen );
   3173 	}
   3174 	pb->pb_op->o_bd = be_orig;
   3175 
   3176 	return ( rc == LDAP_SUCCESS ) ? 0 : 1;
   3177 }
   3178 
   3179 int slapi_entry_rdn_values_present( const Slapi_Entry *e )
   3180 {
   3181 	LDAPDN dn;
   3182 	int rc;
   3183 	int i = 0, match = 0;
   3184 
   3185 	rc = ldap_bv2dn( &((Entry *)e)->e_name, &dn, LDAP_DN_FORMAT_LDAPV3 );
   3186 	if ( rc != LDAP_SUCCESS ) {
   3187 		return 0;
   3188 	}
   3189 
   3190 	if ( dn[0] != NULL ) {
   3191 		LDAPRDN rdn = dn[0];
   3192 
   3193 		for ( i = 0; rdn[i] != NULL; i++ ) {
   3194 			LDAPAVA *ava = &rdn[0][i];
   3195 			Slapi_Attr *a = NULL;
   3196 
   3197 			if ( slapi_entry_attr_find( (Slapi_Entry *)e, ava->la_attr.bv_val, &a ) == 0 &&
   3198 			     slapi_attr_value_find( a, &ava->la_value ) == 0 )
   3199 				match++;
   3200 		}
   3201 	}
   3202 
   3203 	ldap_dnfree( dn );
   3204 
   3205 	return ( i == match );
   3206 }
   3207 
   3208 int slapi_entry_add_rdn_values( Slapi_Entry *e )
   3209 {
   3210 	LDAPDN dn;
   3211 	int i, rc;
   3212 
   3213 	rc = ldap_bv2dn( &e->e_name, &dn, LDAP_DN_FORMAT_LDAPV3 );
   3214 	if ( rc != LDAP_SUCCESS ) {
   3215 		return rc;
   3216 	}
   3217 
   3218 	if ( dn[0] != NULL ) {
   3219 		LDAPRDN rdn = dn[0];
   3220 		struct berval *vals[2];
   3221 
   3222 		for ( i = 0; rdn[i] != NULL; i++ ) {
   3223 			LDAPAVA *ava = &rdn[0][i];
   3224 			Slapi_Attr *a = NULL;
   3225 
   3226 			if ( slapi_entry_attr_find( e, ava->la_attr.bv_val, &a ) == 0 &&
   3227 			     slapi_attr_value_find( a, &ava->la_value ) == 0 )
   3228 				continue;
   3229 
   3230 			vals[0] = &ava->la_value;
   3231 			vals[1] = NULL;
   3232 
   3233 			slapi_entry_attr_merge( e, ava->la_attr.bv_val, vals );
   3234 		}
   3235 	}
   3236 
   3237 	ldap_dnfree( dn );
   3238 
   3239 	return LDAP_SUCCESS;
   3240 }
   3241 
   3242 const char *slapi_entry_get_uniqueid( const Slapi_Entry *e )
   3243 {
   3244 	Attribute *attr;
   3245 
   3246 	attr = attr_find( e->e_attrs, slap_schema.si_ad_entryUUID );
   3247 	if ( attr == NULL ) {
   3248 		return NULL;
   3249 	}
   3250 
   3251 	if ( attr->a_vals != NULL && attr->a_vals[0].bv_len != 0 ) {
   3252 		return slapi_value_get_string( &attr->a_vals[0] );
   3253 	}
   3254 
   3255 	return NULL;
   3256 }
   3257 
   3258 void slapi_entry_set_uniqueid( Slapi_Entry *e, char *uniqueid )
   3259 {
   3260 	struct berval bv;
   3261 
   3262 	attr_delete ( &e->e_attrs, slap_schema.si_ad_entryUUID );
   3263 
   3264 	bv.bv_val = uniqueid;
   3265 	bv.bv_len = strlen( uniqueid );
   3266 	attr_merge_normalize_one( e, slap_schema.si_ad_entryUUID, &bv, NULL );
   3267 }
   3268 
   3269 LDAP *slapi_ldap_init( char *ldaphost, int ldapport, int secure, int shared )
   3270 {
   3271 	LDAP *ld;
   3272 	char *url;
   3273 	size_t size;
   3274 	int rc;
   3275 
   3276 	size = sizeof("ldap:///");
   3277 	if ( secure ) {
   3278 		size++;
   3279 	}
   3280 	size += strlen( ldaphost );
   3281 	if ( ldapport != 0 ) {
   3282 		size += 32;
   3283 	}
   3284 
   3285 	url = slapi_ch_malloc( size );
   3286 
   3287 	if ( ldapport != 0 ) {
   3288 		rc = snprintf( url, size, "ldap%s://%s:%d/", ( secure ? "s" : "" ), ldaphost, ldapport );
   3289 	} else {
   3290 		rc = snprintf( url, size, "ldap%s://%s/", ( secure ? "s" : "" ), ldaphost );
   3291 	}
   3292 
   3293 	if ( rc > 0 && (size_t) rc < size ) {
   3294 		rc = ldap_initialize( &ld, url );
   3295 	} else {
   3296 		ld = NULL;
   3297 	}
   3298 
   3299 	slapi_ch_free_string( &url );
   3300 
   3301 	return ( rc == LDAP_SUCCESS ) ? ld : NULL;
   3302 }
   3303 
   3304 void slapi_ldap_unbind( LDAP *ld )
   3305 {
   3306 	ldap_unbind_ext_s( ld, NULL, NULL );
   3307 }
   3308 
   3309 int slapi_x_backend_get_flags( const Slapi_Backend *be, unsigned long *flags )
   3310 {
   3311 	if ( be == NULL )
   3312 		return LDAP_PARAM_ERROR;
   3313 
   3314 	*flags = SLAP_DBFLAGS(be);
   3315 
   3316 	return LDAP_SUCCESS;
   3317 }
   3318 
   3319 int
   3320 slapi_int_count_controls( LDAPControl **ctrls )
   3321 {
   3322 	size_t i;
   3323 
   3324 	if ( ctrls == NULL )
   3325 		return 0;
   3326 
   3327 	for ( i = 0; ctrls[i] != NULL; i++ )
   3328 		;
   3329 
   3330 	return i;
   3331 }
   3332 
   3333 int
   3334 slapi_op_abandoned( Slapi_PBlock *pb )
   3335 {
   3336 	if ( pb->pb_op == NULL )
   3337 		return 0;
   3338 
   3339 	return ( pb->pb_op->o_abandon );
   3340 }
   3341 
   3342 char *
   3343 slapi_op_type_to_string(unsigned long type)
   3344 {
   3345 	char *str;
   3346 
   3347 	switch (type) {
   3348 	case SLAPI_OPERATION_BIND:
   3349 		str = "bind";
   3350 		break;
   3351 	case SLAPI_OPERATION_UNBIND:
   3352 		str = "unbind";
   3353 		break;
   3354 	case SLAPI_OPERATION_SEARCH:
   3355 		str = "search";
   3356 		break;
   3357 	case SLAPI_OPERATION_MODIFY:
   3358 		str = "modify";
   3359 		break;
   3360 	case SLAPI_OPERATION_ADD:
   3361 		str = "add";
   3362 		break;
   3363 	case SLAPI_OPERATION_DELETE:
   3364 		str = "delete";
   3365 		break;
   3366 	case SLAPI_OPERATION_MODDN:
   3367 		str = "modrdn";
   3368 		break;
   3369 	case SLAPI_OPERATION_COMPARE:
   3370 		str = "compare";
   3371 		break;
   3372 	case SLAPI_OPERATION_ABANDON:
   3373 		str = "abandon";
   3374 		break;
   3375 	case SLAPI_OPERATION_EXTENDED:
   3376 		str = "extended";
   3377 		break;
   3378 	default:
   3379 		str = "unknown operation type";
   3380 		break;
   3381 	}
   3382 	return str;
   3383 }
   3384 
   3385 unsigned long
   3386 slapi_op_get_type(Slapi_Operation * op)
   3387 {
   3388 	unsigned long type;
   3389 
   3390 	switch ( op->o_tag ) {
   3391 	case LDAP_REQ_BIND:
   3392 		type = SLAPI_OPERATION_BIND;
   3393 		break;
   3394 	case LDAP_REQ_UNBIND:
   3395 		type = SLAPI_OPERATION_UNBIND;
   3396 		break;
   3397 	case LDAP_REQ_SEARCH:
   3398 		type = SLAPI_OPERATION_SEARCH;
   3399 		break;
   3400 	case LDAP_REQ_MODIFY:
   3401 		type = SLAPI_OPERATION_MODIFY;
   3402 		break;
   3403 	case LDAP_REQ_ADD:
   3404 		type = SLAPI_OPERATION_ADD;
   3405 		break;
   3406 	case LDAP_REQ_DELETE:
   3407 		type = SLAPI_OPERATION_DELETE;
   3408 		break;
   3409 	case LDAP_REQ_MODRDN:
   3410 		type = SLAPI_OPERATION_MODDN;
   3411 		break;
   3412 	case LDAP_REQ_COMPARE:
   3413 		type = SLAPI_OPERATION_COMPARE;
   3414 		break;
   3415 	case LDAP_REQ_ABANDON:
   3416 		type = SLAPI_OPERATION_ABANDON;
   3417 		break;
   3418 	case LDAP_REQ_EXTENDED:
   3419 		type = SLAPI_OPERATION_EXTENDED;
   3420 		break;
   3421 	default:
   3422 		type = SLAPI_OPERATION_NONE;
   3423 		break;
   3424 	}
   3425 	return type;
   3426 }
   3427 
   3428 void slapi_be_set_readonly( Slapi_Backend *be, int readonly )
   3429 {
   3430 	if ( be == NULL )
   3431 		return;
   3432 
   3433 	if ( readonly )
   3434 		be->be_restrictops |= SLAP_RESTRICT_OP_WRITES;
   3435 	else
   3436 		be->be_restrictops &= ~(SLAP_RESTRICT_OP_WRITES);
   3437 }
   3438 
   3439 int slapi_be_get_readonly( Slapi_Backend *be )
   3440 {
   3441 	if ( be == NULL )
   3442 		return 0;
   3443 
   3444 	return ( (be->be_restrictops & SLAP_RESTRICT_OP_WRITES) == SLAP_RESTRICT_OP_WRITES );
   3445 }
   3446 
   3447 const char *slapi_x_be_get_updatedn( Slapi_Backend *be )
   3448 {
   3449 	if ( be == NULL )
   3450 		return NULL;
   3451 
   3452 	return be->be_update_ndn.bv_val;
   3453 }
   3454 
   3455 Slapi_Backend *slapi_be_select( const Slapi_DN *sdn )
   3456 {
   3457 	Slapi_Backend *be;
   3458 
   3459 	slapi_sdn_get_ndn( sdn );
   3460 
   3461 	be = select_backend( (struct berval *)&sdn->ndn, 0 );
   3462 
   3463 	return be;
   3464 }
   3465 
   3466 #if 0
   3467 void
   3468 slapi_operation_set_flag(Slapi_Operation *op, unsigned long flag)
   3469 {
   3470 }
   3471 
   3472 void
   3473 slapi_operation_clear_flag(Slapi_Operation *op, unsigned long flag)
   3474 {
   3475 }
   3476 
   3477 int
   3478 slapi_operation_is_flag_set(Slapi_Operation *op, unsigned long flag)
   3479 {
   3480 }
   3481 #endif
   3482 
   3483 #endif /* LDAP_SLAPI */
   3484 
   3485