Home | History | Annotate | Line # | Download | only in slapi
      1 /*	$NetBSD: slapi_pblock.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_pblock.c,v 1.4 2025/09/05 21:16:33 christos Exp $");
     27 
     28 #include "portable.h"
     29 #include <slap.h>
     30 #include <slapi.h>
     31 
     32 #ifdef LDAP_SLAPI
     33 
     34 /* some parameters require a valid connection and operation */
     35 #define PBLOCK_LOCK_CONN( _pb )		do { \
     36 		ldap_pvt_thread_mutex_lock( &(_pb)->pb_conn->c_mutex ); \
     37 	} while (0)
     38 
     39 #define PBLOCK_UNLOCK_CONN( _pb )	do { \
     40 		ldap_pvt_thread_mutex_unlock( &(_pb)->pb_conn->c_mutex ); \
     41 	} while (0)
     42 
     43 /* some parameters are only settable for internal operations */
     44 #define PBLOCK_VALIDATE_IS_INTOP( _pb )	do { if ( (_pb)->pb_intop == 0 ) break; } while ( 0 )
     45 
     46 static slapi_pblock_class_t
     47 pblock_get_param_class( int param )
     48 {
     49 	switch ( param ) {
     50 	case SLAPI_PLUGIN_TYPE:
     51 	case SLAPI_PLUGIN_ARGC:
     52 	case SLAPI_PLUGIN_OPRETURN:
     53 	case SLAPI_PLUGIN_INTOP_RESULT:
     54 	case SLAPI_CONFIG_LINENO:
     55 	case SLAPI_CONFIG_ARGC:
     56 	case SLAPI_BIND_METHOD:
     57 	case SLAPI_MODRDN_DELOLDRDN:
     58 	case SLAPI_SEARCH_SCOPE:
     59 	case SLAPI_SEARCH_DEREF:
     60 	case SLAPI_SEARCH_SIZELIMIT:
     61 	case SLAPI_SEARCH_TIMELIMIT:
     62 	case SLAPI_SEARCH_ATTRSONLY:
     63 	case SLAPI_NENTRIES:
     64 	case SLAPI_CHANGENUMBER:
     65 	case SLAPI_DBSIZE:
     66 	case SLAPI_REQUESTOR_ISROOT:
     67 	case SLAPI_BE_READONLY:
     68 	case SLAPI_BE_LASTMOD:
     69 	case SLAPI_DB2LDIF_PRINTKEY:
     70 	case SLAPI_LDIF2DB_REMOVEDUPVALS:
     71 	case SLAPI_MANAGEDSAIT:
     72 	case SLAPI_X_RELAX:
     73 	case SLAPI_X_OPERATION_NO_SCHEMA_CHECK:
     74 	case SLAPI_IS_REPLICATED_OPERATION:
     75 	case SLAPI_X_CONN_IS_UDP:
     76 	case SLAPI_X_CONN_SSF:
     77 	case SLAPI_RESULT_CODE:
     78 	case SLAPI_LOG_OPERATION:
     79 	case SLAPI_IS_INTERNAL_OPERATION:
     80 		return PBLOCK_CLASS_INTEGER;
     81 		break;
     82 
     83 	case SLAPI_CONN_ID:
     84 	case SLAPI_OPERATION_ID:
     85 	case SLAPI_OPINITIATED_TIME:
     86 	case SLAPI_ABANDON_MSGID:
     87 	case SLAPI_X_OPERATION_DELETE_GLUE_PARENT:
     88 	case SLAPI_OPERATION_MSGID:
     89 		return PBLOCK_CLASS_LONG_INTEGER;
     90 		break;
     91 
     92 	case SLAPI_PLUGIN_DESTROY_FN:
     93 	case SLAPI_PLUGIN_DB_BIND_FN:
     94 	case SLAPI_PLUGIN_DB_UNBIND_FN:
     95 	case SLAPI_PLUGIN_DB_SEARCH_FN:
     96 	case SLAPI_PLUGIN_DB_COMPARE_FN:
     97 	case SLAPI_PLUGIN_DB_MODIFY_FN:
     98 	case SLAPI_PLUGIN_DB_MODRDN_FN:
     99 	case SLAPI_PLUGIN_DB_ADD_FN:
    100 	case SLAPI_PLUGIN_DB_DELETE_FN:
    101 	case SLAPI_PLUGIN_DB_ABANDON_FN:
    102 	case SLAPI_PLUGIN_DB_CONFIG_FN:
    103 	case SLAPI_PLUGIN_CLOSE_FN:
    104 	case SLAPI_PLUGIN_DB_FLUSH_FN:
    105 	case SLAPI_PLUGIN_START_FN:
    106 	case SLAPI_PLUGIN_DB_SEQ_FN:
    107 	case SLAPI_PLUGIN_DB_ENTRY_FN:
    108 	case SLAPI_PLUGIN_DB_REFERRAL_FN:
    109 	case SLAPI_PLUGIN_DB_RESULT_FN:
    110 	case SLAPI_PLUGIN_DB_LDIF2DB_FN:
    111 	case SLAPI_PLUGIN_DB_DB2LDIF_FN:
    112 	case SLAPI_PLUGIN_DB_BEGIN_FN:
    113 	case SLAPI_PLUGIN_DB_COMMIT_FN:
    114 	case SLAPI_PLUGIN_DB_ABORT_FN:
    115 	case SLAPI_PLUGIN_DB_ARCHIVE2DB_FN:
    116 	case SLAPI_PLUGIN_DB_DB2ARCHIVE_FN:
    117 	case SLAPI_PLUGIN_DB_NEXT_SEARCH_ENTRY_FN:
    118 	case SLAPI_PLUGIN_DB_FREE_RESULT_SET_FN:
    119 	case SLAPI_PLUGIN_DB_SIZE_FN:
    120 	case SLAPI_PLUGIN_DB_TEST_FN:
    121 	case SLAPI_PLUGIN_DB_NO_ACL:
    122 	case SLAPI_PLUGIN_EXT_OP_FN:
    123 	case SLAPI_PLUGIN_EXT_OP_OIDLIST:
    124 	case SLAPI_PLUGIN_PRE_BIND_FN:
    125 	case SLAPI_PLUGIN_PRE_UNBIND_FN:
    126 	case SLAPI_PLUGIN_PRE_SEARCH_FN:
    127 	case SLAPI_PLUGIN_PRE_COMPARE_FN:
    128 	case SLAPI_PLUGIN_PRE_MODIFY_FN:
    129 	case SLAPI_PLUGIN_PRE_MODRDN_FN:
    130 	case SLAPI_PLUGIN_PRE_ADD_FN:
    131 	case SLAPI_PLUGIN_PRE_DELETE_FN:
    132 	case SLAPI_PLUGIN_PRE_ABANDON_FN:
    133 	case SLAPI_PLUGIN_PRE_ENTRY_FN:
    134 	case SLAPI_PLUGIN_PRE_REFERRAL_FN:
    135 	case SLAPI_PLUGIN_PRE_RESULT_FN:
    136 	case SLAPI_PLUGIN_INTERNAL_PRE_ADD_FN:
    137 	case SLAPI_PLUGIN_INTERNAL_PRE_MODIFY_FN:
    138 	case SLAPI_PLUGIN_INTERNAL_PRE_MODRDN_FN:
    139 	case SLAPI_PLUGIN_INTERNAL_PRE_DELETE_FN:
    140 	case SLAPI_PLUGIN_BE_PRE_ADD_FN:
    141 	case SLAPI_PLUGIN_BE_PRE_MODIFY_FN:
    142 	case SLAPI_PLUGIN_BE_PRE_MODRDN_FN:
    143 	case SLAPI_PLUGIN_BE_PRE_DELETE_FN:
    144 	case SLAPI_PLUGIN_POST_BIND_FN:
    145 	case SLAPI_PLUGIN_POST_UNBIND_FN:
    146 	case SLAPI_PLUGIN_POST_SEARCH_FN:
    147 	case SLAPI_PLUGIN_POST_COMPARE_FN:
    148 	case SLAPI_PLUGIN_POST_MODIFY_FN:
    149 	case SLAPI_PLUGIN_POST_MODRDN_FN:
    150 	case SLAPI_PLUGIN_POST_ADD_FN:
    151 	case SLAPI_PLUGIN_POST_DELETE_FN:
    152 	case SLAPI_PLUGIN_POST_ABANDON_FN:
    153 	case SLAPI_PLUGIN_POST_ENTRY_FN:
    154 	case SLAPI_PLUGIN_POST_REFERRAL_FN:
    155 	case SLAPI_PLUGIN_POST_RESULT_FN:
    156 	case SLAPI_PLUGIN_INTERNAL_POST_ADD_FN:
    157 	case SLAPI_PLUGIN_INTERNAL_POST_MODIFY_FN:
    158 	case SLAPI_PLUGIN_INTERNAL_POST_MODRDN_FN:
    159 	case SLAPI_PLUGIN_INTERNAL_POST_DELETE_FN:
    160 	case SLAPI_PLUGIN_BE_POST_ADD_FN:
    161 	case SLAPI_PLUGIN_BE_POST_MODIFY_FN:
    162 	case SLAPI_PLUGIN_BE_POST_MODRDN_FN:
    163 	case SLAPI_PLUGIN_BE_POST_DELETE_FN:
    164 	case SLAPI_PLUGIN_MR_FILTER_CREATE_FN:
    165 	case SLAPI_PLUGIN_MR_INDEXER_CREATE_FN:
    166 	case SLAPI_PLUGIN_MR_FILTER_MATCH_FN:
    167 	case SLAPI_PLUGIN_MR_FILTER_INDEX_FN:
    168 	case SLAPI_PLUGIN_MR_FILTER_RESET_FN:
    169 	case SLAPI_PLUGIN_MR_INDEX_FN:
    170 	case SLAPI_PLUGIN_COMPUTE_EVALUATOR_FN:
    171 	case SLAPI_PLUGIN_COMPUTE_SEARCH_REWRITER_FN:
    172 	case SLAPI_PLUGIN_ACL_ALLOW_ACCESS:
    173 	case SLAPI_X_PLUGIN_PRE_GROUP_FN:
    174 	case SLAPI_X_PLUGIN_POST_GROUP_FN:
    175 	case SLAPI_PLUGIN_AUDIT_FN:
    176 	case SLAPI_PLUGIN_INTERNAL_PRE_BIND_FN:
    177 	case SLAPI_PLUGIN_INTERNAL_PRE_UNBIND_FN:
    178 	case SLAPI_PLUGIN_INTERNAL_PRE_SEARCH_FN:
    179 	case SLAPI_PLUGIN_INTERNAL_PRE_COMPARE_FN:
    180 	case SLAPI_PLUGIN_INTERNAL_PRE_ABANDON_FN:
    181 	case SLAPI_PLUGIN_INTERNAL_POST_BIND_FN:
    182 	case SLAPI_PLUGIN_INTERNAL_POST_UNBIND_FN:
    183 	case SLAPI_PLUGIN_INTERNAL_POST_SEARCH_FN:
    184 	case SLAPI_PLUGIN_INTERNAL_POST_COMPARE_FN:
    185 	case SLAPI_PLUGIN_INTERNAL_POST_ABANDON_FN:
    186 		return PBLOCK_CLASS_FUNCTION_POINTER;
    187 		break;
    188 
    189 	case SLAPI_BACKEND:
    190 	case SLAPI_CONNECTION:
    191 	case SLAPI_OPERATION:
    192 	case SLAPI_OPERATION_PARAMETERS:
    193 	case SLAPI_OPERATION_TYPE:
    194 	case SLAPI_OPERATION_AUTHTYPE:
    195 	case SLAPI_BE_MONITORDN:
    196 	case SLAPI_BE_TYPE:
    197 	case SLAPI_REQUESTOR_DN:
    198 	case SLAPI_CONN_DN:
    199 	case SLAPI_CONN_CLIENTIP:
    200 	case SLAPI_CONN_SERVERIP:
    201 	case SLAPI_CONN_AUTHTYPE:
    202 	case SLAPI_CONN_AUTHMETHOD:
    203 	case SLAPI_CONN_CERT:
    204 	case SLAPI_X_CONN_CLIENTPATH:
    205 	case SLAPI_X_CONN_SERVERPATH:
    206 	case SLAPI_X_CONN_SASL_CONTEXT:
    207 	case SLAPI_X_CONFIG_ARGV:
    208 	case SLAPI_X_INTOP_FLAGS:
    209 	case SLAPI_X_INTOP_RESULT_CALLBACK:
    210 	case SLAPI_X_INTOP_SEARCH_ENTRY_CALLBACK:
    211 	case SLAPI_X_INTOP_REFERRAL_ENTRY_CALLBACK:
    212 	case SLAPI_X_INTOP_CALLBACK_DATA:
    213 	case SLAPI_PLUGIN_MR_OID:
    214 	case SLAPI_PLUGIN_MR_TYPE:
    215 	case SLAPI_PLUGIN_MR_VALUE:
    216 	case SLAPI_PLUGIN_MR_VALUES:
    217 	case SLAPI_PLUGIN_MR_KEYS:
    218 	case SLAPI_PLUGIN:
    219 	case SLAPI_PLUGIN_PRIVATE:
    220 	case SLAPI_PLUGIN_ARGV:
    221 	case SLAPI_PLUGIN_OBJECT:
    222 	case SLAPI_PLUGIN_DESCRIPTION:
    223 	case SLAPI_PLUGIN_IDENTITY:
    224 	case SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES:
    225 	case SLAPI_PLUGIN_INTOP_SEARCH_REFERRALS:
    226 	case SLAPI_PLUGIN_MR_FILTER_REUSABLE:
    227 	case SLAPI_PLUGIN_MR_QUERY_OPERATOR:
    228 	case SLAPI_PLUGIN_MR_USAGE:
    229 	case SLAPI_OP_LESS:
    230 	case SLAPI_OP_LESS_OR_EQUAL:
    231 	case SLAPI_PLUGIN_MR_USAGE_INDEX:
    232 	case SLAPI_PLUGIN_SYNTAX_FILTER_AVA:
    233 	case SLAPI_PLUGIN_SYNTAX_FILTER_SUB:
    234 	case SLAPI_PLUGIN_SYNTAX_VALUES2KEYS:
    235 	case SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_AVA:
    236 	case SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_SUB:
    237 	case SLAPI_PLUGIN_SYNTAX_NAMES:
    238 	case SLAPI_PLUGIN_SYNTAX_OID:
    239 	case SLAPI_PLUGIN_SYNTAX_FLAGS:
    240 	case SLAPI_PLUGIN_SYNTAX_COMPARE:
    241 	case SLAPI_CONFIG_FILENAME:
    242 	case SLAPI_CONFIG_ARGV:
    243 	case SLAPI_TARGET_ADDRESS:
    244 	case SLAPI_TARGET_UNIQUEID:
    245 	case SLAPI_TARGET_DN:
    246 	case SLAPI_REQCONTROLS:
    247 	case SLAPI_ENTRY_PRE_OP:
    248 	case SLAPI_ENTRY_POST_OP:
    249 	case SLAPI_RESCONTROLS:
    250 	case SLAPI_X_OLD_RESCONTROLS:
    251 	case SLAPI_ADD_RESCONTROL:
    252 	case SLAPI_CONTROLS_ARG:
    253 	case SLAPI_ADD_ENTRY:
    254 	case SLAPI_ADD_EXISTING_DN_ENTRY:
    255 	case SLAPI_ADD_PARENT_ENTRY:
    256 	case SLAPI_ADD_PARENT_UNIQUEID:
    257 	case SLAPI_ADD_EXISTING_UNIQUEID_ENTRY:
    258 	case SLAPI_BIND_CREDENTIALS:
    259 	case SLAPI_BIND_SASLMECHANISM:
    260 	case SLAPI_BIND_RET_SASLCREDS:
    261 	case SLAPI_COMPARE_TYPE:
    262 	case SLAPI_COMPARE_VALUE:
    263 	case SLAPI_MODIFY_MODS:
    264 	case SLAPI_MODRDN_NEWRDN:
    265 	case SLAPI_MODRDN_NEWSUPERIOR:
    266 	case SLAPI_MODRDN_PARENT_ENTRY:
    267 	case SLAPI_MODRDN_NEWPARENT_ENTRY:
    268 	case SLAPI_MODRDN_TARGET_ENTRY:
    269 	case SLAPI_MODRDN_NEWSUPERIOR_ADDRESS:
    270 	case SLAPI_SEARCH_FILTER:
    271 	case SLAPI_SEARCH_STRFILTER:
    272 	case SLAPI_SEARCH_ATTRS:
    273 	case SLAPI_SEQ_TYPE:
    274 	case SLAPI_SEQ_ATTRNAME:
    275 	case SLAPI_SEQ_VAL:
    276 	case SLAPI_EXT_OP_REQ_OID:
    277 	case SLAPI_EXT_OP_REQ_VALUE:
    278 	case SLAPI_EXT_OP_RET_OID:
    279 	case SLAPI_EXT_OP_RET_VALUE:
    280 	case SLAPI_MR_FILTER_ENTRY:
    281 	case SLAPI_MR_FILTER_TYPE:
    282 	case SLAPI_MR_FILTER_VALUE:
    283 	case SLAPI_MR_FILTER_OID:
    284 	case SLAPI_MR_FILTER_DNATTRS:
    285 	case SLAPI_LDIF2DB_FILE:
    286 	case SLAPI_PARENT_TXN:
    287 	case SLAPI_TXN:
    288 	case SLAPI_SEARCH_RESULT_SET:
    289 	case SLAPI_SEARCH_RESULT_ENTRY:
    290 	case SLAPI_SEARCH_REFERRALS:
    291 	case SLAPI_RESULT_TEXT:
    292 	case SLAPI_RESULT_MATCHED:
    293 	case SLAPI_X_GROUP_ENTRY:
    294 	case SLAPI_X_GROUP_ATTRIBUTE:
    295 	case SLAPI_X_GROUP_OPERATION_DN:
    296 	case SLAPI_X_GROUP_TARGET_ENTRY:
    297 	case SLAPI_X_ADD_STRUCTURAL_CLASS:
    298 	case SLAPI_PLUGIN_AUDIT_DATA:
    299 	case SLAPI_IBM_PBLOCK:
    300 	case SLAPI_PLUGIN_VERSION:
    301 		return PBLOCK_CLASS_POINTER;
    302 		break;
    303 	default:
    304 		break;
    305 	}
    306 
    307 	return PBLOCK_CLASS_INVALID;
    308 }
    309 
    310 static void
    311 pblock_lock( Slapi_PBlock *pb )
    312 {
    313 	ldap_pvt_thread_mutex_lock( &pb->pb_mutex );
    314 }
    315 
    316 static void
    317 pblock_unlock( Slapi_PBlock *pb )
    318 {
    319 	ldap_pvt_thread_mutex_unlock( &pb->pb_mutex );
    320 }
    321 
    322 static int
    323 pblock_get_default( Slapi_PBlock *pb, int param, void **value )
    324 {
    325 	int i;
    326 	slapi_pblock_class_t pbClass;
    327 
    328 	pbClass = pblock_get_param_class( param );
    329 	if ( pbClass == PBLOCK_CLASS_INVALID ) {
    330 		return PBLOCK_ERROR;
    331 	}
    332 
    333 	switch ( pbClass ) {
    334 	case PBLOCK_CLASS_INTEGER:
    335 		*((int *)value) = 0;
    336 		break;
    337 	case PBLOCK_CLASS_LONG_INTEGER:
    338 		*((long *)value) = 0L;
    339 		break;
    340 	case PBLOCK_CLASS_POINTER:
    341 	case PBLOCK_CLASS_FUNCTION_POINTER:
    342 		*value = NULL;
    343 		break;
    344 	case PBLOCK_CLASS_INVALID:
    345 		return PBLOCK_ERROR;
    346 	}
    347 
    348 	for ( i = 0; i < pb->pb_nParams; i++ ) {
    349 		if ( pb->pb_params[i] == param ) {
    350 			switch ( pbClass ) {
    351 			case PBLOCK_CLASS_INTEGER:
    352 				*((int *)value) = pb->pb_values[i].pv_integer;
    353 				break;
    354 			case PBLOCK_CLASS_LONG_INTEGER:
    355 				*((long *)value) = pb->pb_values[i].pv_long_integer;
    356 				break;
    357 			case PBLOCK_CLASS_POINTER:
    358 				*value = pb->pb_values[i].pv_pointer;
    359 				break;
    360 			case PBLOCK_CLASS_FUNCTION_POINTER:
    361 				*value = pb->pb_values[i].pv_function_pointer;
    362 				break;
    363 			default:
    364 				break;
    365 			}
    366 			break;
    367 	  	}
    368 	}
    369 
    370 	return PBLOCK_SUCCESS;
    371 }
    372 
    373 static char *
    374 pblock_get_authtype( AuthorizationInformation *authz, int is_tls )
    375 {
    376 	char *authType;
    377 
    378 	switch ( authz->sai_method ) {
    379 	case LDAP_AUTH_SASL:
    380 		authType = SLAPD_AUTH_SASL;
    381 		break;
    382 	case LDAP_AUTH_SIMPLE:
    383 		authType = SLAPD_AUTH_SIMPLE;
    384 		break;
    385 	case LDAP_AUTH_NONE:
    386 		authType = SLAPD_AUTH_NONE;
    387 		break;
    388 	default:
    389 		authType = NULL;
    390 		break;
    391 	}
    392 
    393 	if ( is_tls && authType == NULL ) {
    394 		authType = SLAPD_AUTH_SSL;
    395 	}
    396 
    397 	return authType;
    398 }
    399 
    400 static int
    401 pblock_set_default( Slapi_PBlock *pb, int param, void *value )
    402 {
    403 	slapi_pblock_class_t pbClass;
    404 	int i;
    405 
    406 	pbClass = pblock_get_param_class( param );
    407 	if ( pbClass == PBLOCK_CLASS_INVALID ) {
    408 		return PBLOCK_ERROR;
    409 	}
    410 
    411 	if ( pb->pb_nParams == PBLOCK_MAX_PARAMS ) {
    412 		return PBLOCK_ERROR;
    413 	}
    414 
    415 	for ( i = 0; i < pb->pb_nParams; i++ ) {
    416 		if ( pb->pb_params[i] == param )
    417 			break;
    418 	}
    419 	if ( i >= pb->pb_nParams ) {
    420 		pb->pb_params[i] = param;
    421 	  	pb->pb_nParams++;
    422 	}
    423 
    424 	switch ( pbClass ) {
    425 	case PBLOCK_CLASS_INTEGER:
    426 		pb->pb_values[i].pv_integer = (*((int *)value));
    427 		break;
    428 	case PBLOCK_CLASS_LONG_INTEGER:
    429 		pb->pb_values[i].pv_long_integer = (*((long *)value));
    430 		break;
    431 	case PBLOCK_CLASS_POINTER:
    432 		pb->pb_values[i].pv_pointer = value;
    433 		break;
    434 	case PBLOCK_CLASS_FUNCTION_POINTER:
    435 		pb->pb_values[i].pv_function_pointer = value;
    436 		break;
    437 	default:
    438 		break;
    439 	}
    440 
    441 	return PBLOCK_SUCCESS;
    442 }
    443 
    444 static int
    445 pblock_be_call( Slapi_PBlock *pb, int (*bep)(Operation *) )
    446 {
    447 	BackendDB *be_orig;
    448 	Operation *op;
    449 	int rc;
    450 
    451 	PBLOCK_ASSERT_OP( pb, 0 );
    452 	op = pb->pb_op;
    453 
    454 	be_orig = op->o_bd;
    455 	op->o_bd = select_backend( &op->o_req_ndn, 0 );
    456 	rc = (*bep)( op );
    457 	op->o_bd = be_orig;
    458 
    459 	return rc;
    460 }
    461 
    462 static int
    463 pblock_get( Slapi_PBlock *pb, int param, void **value )
    464 {
    465 	int rc = PBLOCK_SUCCESS;
    466 
    467 	pblock_lock( pb );
    468 
    469 	switch ( param ) {
    470 	case SLAPI_OPERATION:
    471 		*value = pb->pb_op;
    472 		break;
    473 	case SLAPI_OPINITIATED_TIME:
    474 		PBLOCK_ASSERT_OP( pb, 0 );
    475 		*((long *)value) = pb->pb_op->o_time;
    476 		break;
    477 	case SLAPI_OPERATION_ID:
    478 		PBLOCK_ASSERT_OP( pb, 0 );
    479 		*((long *)value) = pb->pb_op->o_opid;
    480 		break;
    481 	case SLAPI_OPERATION_TYPE:
    482 		PBLOCK_ASSERT_OP( pb, 0 );
    483 		*((ber_tag_t *)value) = pb->pb_op->o_tag;
    484 		break;
    485 	case SLAPI_OPERATION_MSGID:
    486 		PBLOCK_ASSERT_OP( pb, 0 );
    487 		*((long *)value) = pb->pb_op->o_msgid;
    488 		break;
    489 	case SLAPI_X_OPERATION_DELETE_GLUE_PARENT:
    490 		PBLOCK_ASSERT_OP( pb, 0 );
    491 		*((int *)value) = pb->pb_op->o_delete_glue_parent;
    492 		break;
    493 	case SLAPI_X_OPERATION_NO_SCHEMA_CHECK:
    494 		PBLOCK_ASSERT_OP( pb, 0 );
    495 		*((int *)value) = get_no_schema_check( pb->pb_op );
    496 		break;
    497 	case SLAPI_X_ADD_STRUCTURAL_CLASS:
    498 		PBLOCK_ASSERT_OP( pb, 0 );
    499 
    500 		if ( pb->pb_op->o_tag == LDAP_REQ_ADD ) {
    501 			struct berval tmpval = BER_BVNULL;
    502 
    503 			rc = mods_structural_class( pb->pb_op->ora_modlist,
    504 				&tmpval, &pb->pb_rs->sr_text,
    505 				pb->pb_textbuf, sizeof( pb->pb_textbuf ),
    506 				pb->pb_op->o_tmpmemctx );
    507 			*((char **)value) = tmpval.bv_val;
    508 		} else {
    509 			rc = PBLOCK_ERROR;
    510 		}
    511 		break;
    512 	case SLAPI_X_OPERATION_NO_SUBORDINATE_GLUE:
    513 		PBLOCK_ASSERT_OP( pb, 0 );
    514 		*((int *)value) = pb->pb_op->o_no_subordinate_glue;
    515 		break;
    516 	case SLAPI_REQCONTROLS:
    517 		PBLOCK_ASSERT_OP( pb, 0 );
    518 		*((LDAPControl ***)value) = pb->pb_op->o_ctrls;
    519 		break;
    520 	case SLAPI_REQUESTOR_DN:
    521 		PBLOCK_ASSERT_OP( pb, 0 );
    522 		*((char **)value) = pb->pb_op->o_dn.bv_val;
    523 		break;
    524 	case SLAPI_MANAGEDSAIT:
    525 		PBLOCK_ASSERT_OP( pb, 0 );
    526 		*((int *)value) = get_manageDSAit( pb->pb_op );
    527 		break;
    528 	case SLAPI_X_RELAX:
    529 		PBLOCK_ASSERT_OP( pb, 0 );
    530 		*((int *)value) = get_relax( pb->pb_op );
    531 		break;
    532 	case SLAPI_BACKEND:
    533 		PBLOCK_ASSERT_OP( pb, 0 );
    534 		*((BackendDB **)value) = select_backend( &pb->pb_op->o_req_ndn, 0 );
    535 		break;
    536 	case SLAPI_BE_TYPE:
    537 		PBLOCK_ASSERT_OP( pb, 0 );
    538 		if ( pb->pb_op->o_bd != NULL )
    539 			*((char **)value) = pb->pb_op->o_bd->bd_info->bi_type;
    540 		else
    541 			*value = NULL;
    542 		break;
    543 	case SLAPI_CONNECTION:
    544 		*value = pb->pb_conn;
    545 		break;
    546 	case SLAPI_X_CONN_SSF:
    547 		PBLOCK_ASSERT_OP( pb, 0 );
    548 		*((slap_ssf_t *)value) = pb->pb_conn->c_ssf;
    549 		break;
    550 	case SLAPI_X_CONN_SASL_CONTEXT:
    551 		PBLOCK_ASSERT_CONN( pb );
    552 		if ( pb->pb_conn->c_sasl_authctx != NULL )
    553 			*value = pb->pb_conn->c_sasl_authctx;
    554 		else
    555 			*value = pb->pb_conn->c_sasl_sockctx;
    556 		break;
    557 	case SLAPI_TARGET_DN:
    558 		PBLOCK_ASSERT_OP( pb, 0 );
    559 		*((char **)value) = pb->pb_op->o_req_dn.bv_val;
    560 		break;
    561 	case SLAPI_REQUESTOR_ISROOT:
    562 		*((int *)value) = pblock_be_call( pb, be_isroot );
    563 		break;
    564 	case SLAPI_IS_REPLICATED_OPERATION:
    565 		*((int *)value) = pblock_be_call( pb, be_slurp_update );
    566 		break;
    567 	case SLAPI_CONN_AUTHTYPE:
    568 	case SLAPI_CONN_AUTHMETHOD: /* XXX should return SASL mech */
    569 		PBLOCK_ASSERT_CONN( pb );
    570 		*((char **)value) = pblock_get_authtype( &pb->pb_conn->c_authz,
    571 #ifdef HAVE_TLS
    572 							 pb->pb_conn->c_is_tls
    573 #else
    574 							 0
    575 #endif
    576 							 );
    577 		break;
    578 	case SLAPI_IS_INTERNAL_OPERATION:
    579 		*((int *)value) = pb->pb_intop;
    580 		break;
    581 	case SLAPI_X_CONN_IS_UDP:
    582 		PBLOCK_ASSERT_CONN( pb );
    583 #ifdef LDAP_CONNECTIONLESS
    584 		*((int *)value) = pb->pb_conn->c_is_udp;
    585 #else
    586 		*((int *)value) = 0;
    587 #endif
    588 		break;
    589 	case SLAPI_CONN_ID:
    590 		PBLOCK_ASSERT_CONN( pb );
    591 		*((long *)value) = pb->pb_conn->c_connid;
    592 		break;
    593 	case SLAPI_CONN_DN:
    594 		PBLOCK_ASSERT_CONN( pb );
    595 #if 0
    596 		/* This would be necessary to keep plugin compat after the fix in ITS#4158 */
    597 		if ( pb->pb_op->o_tag == LDAP_REQ_BIND && pb->pb_rs->sr_err == LDAP_SUCCESS )
    598 			*((char **)value) = pb->pb_op->orb_edn.bv_val;
    599 		else
    600 #endif
    601 		*((char **)value) = pb->pb_conn->c_dn.bv_val;
    602 		break;
    603 	case SLAPI_CONN_CLIENTIP:
    604 		PBLOCK_ASSERT_CONN( pb );
    605 		if ( strncmp( pb->pb_conn->c_peer_name.bv_val, "IP=", 3 ) == 0 )
    606 			*((char **)value) = &pb->pb_conn->c_peer_name.bv_val[3];
    607 		else
    608 			*value = NULL;
    609 		break;
    610 	case SLAPI_X_CONN_CLIENTPATH:
    611 		PBLOCK_ASSERT_CONN( pb );
    612 		if ( strncmp( pb->pb_conn->c_peer_name.bv_val, "PATH=", 3 ) == 0 )
    613 			*((char **)value) = &pb->pb_conn->c_peer_name.bv_val[5];
    614 		else
    615 			*value = NULL;
    616 		break;
    617 	case SLAPI_CONN_SERVERIP:
    618 		PBLOCK_ASSERT_CONN( pb );
    619 		if ( strncmp( pb->pb_conn->c_sock_name.bv_val, "IP=", 3 ) == 0 )
    620 			*((char **)value) = &pb->pb_conn->c_sock_name.bv_val[3];
    621 		else
    622 			*value = NULL;
    623 		break;
    624 	case SLAPI_X_CONN_SERVERPATH:
    625 		PBLOCK_ASSERT_CONN( pb );
    626 		if ( strncmp( pb->pb_conn->c_sock_name.bv_val, "PATH=", 3 ) == 0 )
    627 			*((char **)value) = &pb->pb_conn->c_sock_name.bv_val[5];
    628 		else
    629 			*value = NULL;
    630 		break;
    631 	case SLAPI_RESULT_CODE:
    632 	case SLAPI_PLUGIN_INTOP_RESULT:
    633 		PBLOCK_ASSERT_OP( pb, 0 );
    634 		*((int *)value) = pb->pb_rs->sr_err;
    635 		break;
    636         case SLAPI_RESULT_TEXT:
    637 		PBLOCK_ASSERT_OP( pb, 0 );
    638 		*((const char **)value) = pb->pb_rs->sr_text;
    639 		break;
    640         case SLAPI_RESULT_MATCHED:
    641 		PBLOCK_ASSERT_OP( pb, 0 );
    642 		*((const char **)value) = pb->pb_rs->sr_matched;
    643 		break;
    644 	case SLAPI_ADD_ENTRY:
    645 		PBLOCK_ASSERT_OP( pb, 0 );
    646 		if ( pb->pb_op->o_tag == LDAP_REQ_ADD )
    647 			*((Slapi_Entry **)value) = pb->pb_op->ora_e;
    648 		else
    649 			*value = NULL;
    650 		break;
    651 	case SLAPI_MODIFY_MODS: {
    652 		LDAPMod **mods = NULL;
    653 		Modifications *ml = NULL;
    654 
    655 		pblock_get_default( pb, param, (void **)&mods );
    656 		if ( mods == NULL && pb->pb_intop == 0 ) {
    657 			switch ( pb->pb_op->o_tag ) {
    658 			case LDAP_REQ_MODIFY:
    659 				ml = pb->pb_op->orm_modlist;
    660 				break;
    661 			case LDAP_REQ_MODRDN:
    662 				ml = pb->pb_op->orr_modlist;
    663 				break;
    664 			default:
    665 				rc = PBLOCK_ERROR;
    666 				break;
    667 			}
    668 			if ( rc != PBLOCK_ERROR ) {
    669 				mods = slapi_int_modifications2ldapmods( ml );
    670 				pblock_set_default( pb, param, (void *)mods );
    671 			}
    672 		}
    673 		*((LDAPMod ***)value) = mods;
    674 		break;
    675 	}
    676 	case SLAPI_MODRDN_NEWRDN:
    677 		PBLOCK_ASSERT_OP( pb, 0 );
    678 		if ( pb->pb_op->o_tag == LDAP_REQ_MODRDN )
    679 			*((char **)value) = pb->pb_op->orr_newrdn.bv_val;
    680 		else
    681 			*value = NULL;
    682 		break;
    683 	case SLAPI_MODRDN_NEWSUPERIOR:
    684 		PBLOCK_ASSERT_OP( pb, 0 );
    685 		if ( pb->pb_op->o_tag == LDAP_REQ_MODRDN && pb->pb_op->orr_newSup != NULL )
    686 			*((char **)value) = pb->pb_op->orr_newSup->bv_val;
    687 		else
    688 			*value = NULL;
    689 		break;
    690 	case SLAPI_MODRDN_DELOLDRDN:
    691 		PBLOCK_ASSERT_OP( pb, 0 );
    692 		if ( pb->pb_op->o_tag == LDAP_REQ_MODRDN )
    693 			*((int *)value) = pb->pb_op->orr_deleteoldrdn;
    694 		else
    695 			*((int *)value) = 0;
    696 		break;
    697 	case SLAPI_SEARCH_SCOPE:
    698 		PBLOCK_ASSERT_OP( pb, 0 );
    699 		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
    700 			*((int *)value) = pb->pb_op->ors_scope;
    701 		else
    702 			*((int *)value) = 0;
    703 		break;
    704 	case SLAPI_SEARCH_DEREF:
    705 		PBLOCK_ASSERT_OP( pb, 0 );
    706 		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
    707 			*((int *)value) = pb->pb_op->ors_deref;
    708 		else
    709 			*((int *)value) = 0;
    710 		break;
    711 	case SLAPI_SEARCH_SIZELIMIT:
    712 		PBLOCK_ASSERT_OP( pb, 0 );
    713 		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
    714 			*((int *)value) = pb->pb_op->ors_slimit;
    715 		else
    716 			*((int *)value) = 0;
    717 		break;
    718 	case SLAPI_SEARCH_TIMELIMIT:
    719 		PBLOCK_ASSERT_OP( pb, 0 );
    720 		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
    721 			*((int *)value) = pb->pb_op->ors_tlimit;
    722 		else
    723 			*((int *)value) = 0;
    724 		break;
    725 	case SLAPI_SEARCH_FILTER:
    726 		PBLOCK_ASSERT_OP( pb, 0 );
    727 		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
    728 			*((Slapi_Filter **)value) = pb->pb_op->ors_filter;
    729 		else
    730 			*((Slapi_Filter **)value) = NULL;
    731 		break;
    732 	case SLAPI_SEARCH_STRFILTER:
    733 		PBLOCK_ASSERT_OP( pb, 0 );
    734 		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
    735 			*((char **)value) = pb->pb_op->ors_filterstr.bv_val;
    736 		else
    737 			*((char **)value) = NULL;
    738 		break;
    739 	case SLAPI_SEARCH_ATTRS: {
    740 		char **attrs = NULL;
    741 
    742 		PBLOCK_ASSERT_OP( pb, 0 );
    743 		if ( pb->pb_op->o_tag != LDAP_REQ_SEARCH ) {
    744 			rc = PBLOCK_ERROR;
    745 			break;
    746 		}
    747 		pblock_get_default( pb, param, (void **)&attrs );
    748 		if ( attrs == NULL && pb->pb_intop == 0 ) {
    749 			attrs = anlist2charray_x( pb->pb_op->ors_attrs, 0, pb->pb_op->o_tmpmemctx );
    750 			pblock_set_default( pb, param, (void *)attrs );
    751 		}
    752 		*((char ***)value) = attrs;
    753 		break;
    754 	}
    755 	case SLAPI_SEARCH_ATTRSONLY:
    756 		PBLOCK_ASSERT_OP( pb, 0 );
    757 		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
    758 			*((int *)value) = pb->pb_op->ors_attrsonly;
    759 		else
    760 			*((int *)value) = 0;
    761 		break;
    762 	case SLAPI_SEARCH_RESULT_ENTRY:
    763 		PBLOCK_ASSERT_OP( pb, 0 );
    764 		*((Slapi_Entry **)value) = pb->pb_rs->sr_entry;
    765 		break;
    766 	case SLAPI_BIND_RET_SASLCREDS:
    767 		PBLOCK_ASSERT_OP( pb, 0 );
    768 		*((struct berval **)value) = pb->pb_rs->sr_sasldata;
    769 		break;
    770 	case SLAPI_EXT_OP_REQ_OID:
    771 		*((const char **)value) = pb->pb_op->ore_reqoid.bv_val;
    772 		break;
    773 	case SLAPI_EXT_OP_REQ_VALUE:
    774 		*((struct berval **)value) = pb->pb_op->ore_reqdata;
    775 		break;
    776 	case SLAPI_EXT_OP_RET_OID:
    777 		PBLOCK_ASSERT_OP( pb, 0 );
    778 		*((const char **)value) = pb->pb_rs->sr_rspoid;
    779 		break;
    780 	case SLAPI_EXT_OP_RET_VALUE:
    781 		PBLOCK_ASSERT_OP( pb, 0 );
    782 		*((struct berval **)value) = pb->pb_rs->sr_rspdata;
    783 		break;
    784 	case SLAPI_BIND_METHOD:
    785 		if ( pb->pb_op->o_tag == LDAP_REQ_BIND )
    786 			*((int *)value) = pb->pb_op->orb_method;
    787 		else
    788 			*((int *)value) = 0;
    789 		break;
    790 	case SLAPI_BIND_CREDENTIALS:
    791 		if ( pb->pb_op->o_tag == LDAP_REQ_BIND )
    792 			*((struct berval **)value) = &pb->pb_op->orb_cred;
    793 		else
    794 			*value = NULL;
    795 		break;
    796 	case SLAPI_COMPARE_TYPE:
    797 		if ( pb->pb_op->o_tag == LDAP_REQ_COMPARE )
    798 			*((char **)value) = pb->pb_op->orc_ava->aa_desc->ad_cname.bv_val;
    799 		else
    800 			*value = NULL;
    801 		break;
    802 	case SLAPI_COMPARE_VALUE:
    803 		if ( pb->pb_op->o_tag == LDAP_REQ_COMPARE )
    804 			*((struct berval **)value) = &pb->pb_op->orc_ava->aa_value;
    805 		else
    806 			*value = NULL;
    807 		break;
    808 	case SLAPI_ABANDON_MSGID:
    809 		if ( pb->pb_op->o_tag == LDAP_REQ_ABANDON )
    810 			*((int *)value) = pb->pb_op->orn_msgid;
    811 		else
    812 			*((int *)value) = 0;
    813 		break;
    814 	default:
    815 		rc = pblock_get_default( pb, param, value );
    816 		break;
    817 	}
    818 
    819 	pblock_unlock( pb );
    820 
    821 	return rc;
    822 }
    823 
    824 static int
    825 pblock_add_control( Slapi_PBlock *pb, LDAPControl *control )
    826 {
    827 	LDAPControl **controls = NULL;
    828 	size_t i;
    829 
    830 	pblock_get_default( pb, SLAPI_RESCONTROLS, (void **)&controls );
    831 
    832 	if ( controls != NULL ) {
    833 		for ( i = 0; controls[i] != NULL; i++ )
    834 			;
    835 	} else {
    836 		i = 0;
    837 	}
    838 
    839 	controls = (LDAPControl **)slapi_ch_realloc( (char *)controls,
    840 		( i + 2 ) * sizeof(LDAPControl *));
    841 	controls[i++] = slapi_dup_control( control );
    842 	controls[i] = NULL;
    843 
    844 	return pblock_set_default( pb, SLAPI_RESCONTROLS, (void *)controls );
    845 }
    846 
    847 static int
    848 pblock_set_dn( void *value, struct berval *dn, struct berval *ndn, void *memctx )
    849 {
    850 	struct berval bv;
    851 
    852 	if ( !BER_BVISNULL( dn )) {
    853 		slap_sl_free( dn->bv_val, memctx );
    854 		BER_BVZERO( dn );
    855 	}
    856 	if ( !BER_BVISNULL( ndn )) {
    857 		slap_sl_free( ndn->bv_val, memctx );
    858 		BER_BVZERO( ndn );
    859 	}
    860 
    861 	bv.bv_val = (char *)value;
    862 	bv.bv_len = ( value != NULL ) ? strlen( bv.bv_val ) : 0;
    863 
    864 	return dnPrettyNormal( NULL, &bv, dn, ndn, memctx );
    865 }
    866 
    867 static int
    868 pblock_set( Slapi_PBlock *pb, int param, void *value )
    869 {
    870 	int rc = PBLOCK_SUCCESS;
    871 
    872 	pblock_lock( pb );
    873 
    874 	switch ( param ) {
    875 	case SLAPI_OPERATION:
    876 		pb->pb_op = (Operation *)value;
    877 		break;
    878 	case SLAPI_OPINITIATED_TIME:
    879 		PBLOCK_ASSERT_OP( pb, 0 );
    880 		pb->pb_op->o_time = *((long *)value);
    881 		break;
    882 	case SLAPI_OPERATION_ID:
    883 		PBLOCK_ASSERT_OP( pb, 0 );
    884 		pb->pb_op->o_opid = *((long *)value);
    885 		break;
    886 	case SLAPI_OPERATION_TYPE:
    887 		PBLOCK_ASSERT_OP( pb, 0 );
    888 		pb->pb_op->o_tag = *((ber_tag_t *)value);
    889 		break;
    890 	case SLAPI_OPERATION_MSGID:
    891 		PBLOCK_ASSERT_OP( pb, 0 );
    892 		pb->pb_op->o_msgid = *((long *)value);
    893 		break;
    894 	case SLAPI_X_OPERATION_DELETE_GLUE_PARENT:
    895 		PBLOCK_ASSERT_OP( pb, 0 );
    896 		pb->pb_op->o_delete_glue_parent = *((int *)value);
    897 		break;
    898 	case SLAPI_X_OPERATION_NO_SCHEMA_CHECK:
    899 		PBLOCK_ASSERT_OP( pb, 0 );
    900 		pb->pb_op->o_no_schema_check = *((int *)value);
    901 		break;
    902 	case SLAPI_X_OPERATION_NO_SUBORDINATE_GLUE:
    903 		PBLOCK_ASSERT_OP( pb, 0 );
    904 		pb->pb_op->o_no_subordinate_glue = *((int *)value);
    905 		break;
    906 	case SLAPI_REQCONTROLS:
    907 		PBLOCK_ASSERT_OP( pb, 0 );
    908 		pb->pb_op->o_ctrls = (LDAPControl **)value;
    909 		break;
    910 	case SLAPI_RESCONTROLS: {
    911 		LDAPControl **ctrls = NULL;
    912 
    913 		pblock_get_default( pb, param, (void **)&ctrls );
    914 		if ( ctrls != NULL ) {
    915 			/* free old ones first */
    916 			ldap_controls_free( ctrls );
    917 		}
    918 		rc = pblock_set_default( pb, param, value );
    919 		break;
    920 	}
    921 	case SLAPI_ADD_RESCONTROL:
    922 		PBLOCK_ASSERT_OP( pb, 0 );
    923 		rc = pblock_add_control( pb, (LDAPControl *)value );
    924 		break;
    925 	case SLAPI_REQUESTOR_DN:
    926 		PBLOCK_ASSERT_OP( pb, 0 );
    927 		rc = pblock_set_dn( value, &pb->pb_op->o_dn, &pb->pb_op->o_ndn, pb->pb_op->o_tmpmemctx );
    928 		break;
    929 	case SLAPI_MANAGEDSAIT:
    930 		PBLOCK_ASSERT_OP( pb, 0 );
    931 		pb->pb_op->o_managedsait = *((int *)value);
    932 		break;
    933 	case SLAPI_X_RELAX:
    934 		PBLOCK_ASSERT_OP( pb, 0 );
    935 		pb->pb_op->o_relax = *((int *)value);
    936 		break;
    937 	case SLAPI_BACKEND:
    938 		PBLOCK_ASSERT_OP( pb, 0 );
    939 		pb->pb_op->o_bd = (BackendDB *)value;
    940 		break;
    941 	case SLAPI_CONNECTION:
    942 		pb->pb_conn = (Connection *)value;
    943 		break;
    944 	case SLAPI_X_CONN_SSF:
    945 		PBLOCK_ASSERT_CONN( pb );
    946 		PBLOCK_LOCK_CONN( pb );
    947 		pb->pb_conn->c_ssf = (slap_ssf_t)(long)value;
    948 		PBLOCK_UNLOCK_CONN( pb );
    949 		break;
    950 	case SLAPI_X_CONN_SASL_CONTEXT:
    951 		PBLOCK_ASSERT_CONN( pb );
    952 		PBLOCK_LOCK_CONN( pb );
    953 		pb->pb_conn->c_sasl_authctx = value;
    954 		PBLOCK_UNLOCK_CONN( pb );
    955 		break;
    956 	case SLAPI_TARGET_DN:
    957 		PBLOCK_ASSERT_OP( pb, 0 );
    958 		rc = pblock_set_dn( value, &pb->pb_op->o_req_dn, &pb->pb_op->o_req_ndn, pb->pb_op->o_tmpmemctx );
    959 		break;
    960 	case SLAPI_CONN_ID:
    961 		PBLOCK_ASSERT_CONN( pb );
    962 		PBLOCK_LOCK_CONN( pb );
    963 		pb->pb_conn->c_connid = *((long *)value);
    964 		PBLOCK_UNLOCK_CONN( pb );
    965 		break;
    966 	case SLAPI_CONN_DN:
    967 		PBLOCK_ASSERT_CONN( pb );
    968 		PBLOCK_LOCK_CONN( pb );
    969 		rc = pblock_set_dn( value, &pb->pb_conn->c_dn, &pb->pb_conn->c_ndn, NULL );
    970 		PBLOCK_UNLOCK_CONN( pb );
    971 		break;
    972 	case SLAPI_RESULT_CODE:
    973 	case SLAPI_PLUGIN_INTOP_RESULT:
    974 		PBLOCK_ASSERT_OP( pb, 0 );
    975 		pb->pb_rs->sr_err = *((int *)value);
    976 		break;
    977 	case SLAPI_RESULT_TEXT:
    978 		PBLOCK_ASSERT_OP( pb, 0 );
    979 		snprintf( pb->pb_textbuf, sizeof( pb->pb_textbuf ), "%s", (char *)value );
    980 		pb->pb_rs->sr_text = pb->pb_textbuf;
    981 		break;
    982 	case SLAPI_RESULT_MATCHED:
    983 		PBLOCK_ASSERT_OP( pb, 0 );
    984 		pb->pb_rs->sr_matched = (char *)value; /* XXX should dup? */
    985 		break;
    986 	case SLAPI_ADD_ENTRY:
    987 		PBLOCK_ASSERT_OP( pb, 0 );
    988 		if ( pb->pb_op->o_tag == LDAP_REQ_ADD )
    989 			pb->pb_op->ora_e = (Slapi_Entry *)value;
    990 		else
    991 			rc = PBLOCK_ERROR;
    992 		break;
    993 	case SLAPI_MODIFY_MODS: {
    994 		Modifications **mlp;
    995 		Modifications *newmods;
    996 
    997 		PBLOCK_ASSERT_OP( pb, 0 );
    998 		rc = pblock_set_default( pb, param, value );
    999 		if ( rc != PBLOCK_SUCCESS ) {
   1000 			break;
   1001 		}
   1002 
   1003 		if ( pb->pb_op->o_tag == LDAP_REQ_MODIFY ) {
   1004 			mlp = &pb->pb_op->orm_modlist;
   1005 		} else if ( pb->pb_op->o_tag == LDAP_REQ_ADD ) {
   1006 			mlp = &pb->pb_op->ora_modlist;
   1007 		} else if ( pb->pb_op->o_tag == LDAP_REQ_MODRDN ) {
   1008 			mlp = &pb->pb_op->orr_modlist;
   1009 		} else {
   1010 			break;
   1011 		}
   1012 
   1013 		newmods = slapi_int_ldapmods2modifications( pb->pb_op, (LDAPMod **)value );
   1014 		if ( newmods != NULL ) {
   1015 			slap_mods_free( *mlp, 1 );
   1016 			*mlp = newmods;
   1017 		}
   1018 		break;
   1019 	}
   1020 	case SLAPI_MODRDN_NEWRDN:
   1021 		PBLOCK_ASSERT_OP( pb, 0 );
   1022 		PBLOCK_VALIDATE_IS_INTOP( pb );
   1023 		if ( pb->pb_op->o_tag == LDAP_REQ_MODRDN ) {
   1024 			rc = pblock_set_dn( value, &pb->pb_op->orr_newrdn, &pb->pb_op->orr_nnewrdn, pb->pb_op->o_tmpmemctx );
   1025 			if ( rc == LDAP_SUCCESS )
   1026 				rc = rdn_validate( &pb->pb_op->orr_nnewrdn );
   1027 			if ( rc == LDAP_SUCCESS ) {
   1028 				struct berval pdn, pndn;
   1029 				if ( pb->pb_op->orr_nnewSup ) {
   1030 					pdn = *pb->pb_op->orr_newSup;
   1031 					pndn = *pb->pb_op->orr_nnewSup;
   1032 				} else {
   1033 					dnParent( &pb->pb_op->o_req_dn, &pdn );
   1034 					dnParent( &pb->pb_op->o_req_ndn, &pndn );
   1035 				}
   1036 				build_new_dn( &pb->pb_op->orr_newDN, &pdn, &pb->pb_op->orr_newrdn, pb->pb_op->o_tmpmemctx );
   1037 				build_new_dn( &pb->pb_op->orr_nnewDN, &pndn, &pb->pb_op->orr_nnewrdn, pb->pb_op->o_tmpmemctx );
   1038 			}
   1039 		} else {
   1040 			rc = PBLOCK_ERROR;
   1041 		}
   1042 		break;
   1043 	case SLAPI_MODRDN_NEWSUPERIOR:
   1044 		PBLOCK_ASSERT_OP( pb, 0 );
   1045 		PBLOCK_VALIDATE_IS_INTOP( pb );
   1046 		if ( pb->pb_op->o_tag == LDAP_REQ_MODRDN ) {
   1047 			if ( value == NULL ) {
   1048 				struct berval pdn, pndn;
   1049 				if ( pb->pb_op->orr_newSup != NULL ) {
   1050 					pb->pb_op->o_tmpfree( pb->pb_op->orr_newSup, pb->pb_op->o_tmpmemctx );
   1051 					BER_BVZERO( pb->pb_op->orr_newSup );
   1052 					pb->pb_op->orr_newSup = NULL;
   1053 				}
   1054 				if ( pb->pb_op->orr_newSup != NULL ) {
   1055 					pb->pb_op->o_tmpfree( pb->pb_op->orr_nnewSup, pb->pb_op->o_tmpmemctx );
   1056 					BER_BVZERO( pb->pb_op->orr_nnewSup );
   1057 					pb->pb_op->orr_nnewSup = NULL;
   1058 				}
   1059 				dnParent( &pb->pb_op->o_req_dn, &pdn );
   1060 				build_new_dn( &pb->pb_op->orr_newDN, &pdn, &pb->pb_op->orr_newrdn, pb->pb_op->o_tmpmemctx );
   1061 				dnParent( &pb->pb_op->o_req_ndn, &pndn );
   1062 				build_new_dn( &pb->pb_op->orr_nnewDN, &pndn, &pb->pb_op->orr_nnewrdn, pb->pb_op->o_tmpmemctx );
   1063 			} else {
   1064 				if ( pb->pb_op->orr_newSup == NULL ) {
   1065 					pb->pb_op->orr_newSup = (struct berval *)pb->pb_op->o_tmpalloc(
   1066 						sizeof(struct berval), pb->pb_op->o_tmpmemctx );
   1067 					BER_BVZERO( pb->pb_op->orr_newSup );
   1068 				}
   1069 				if ( pb->pb_op->orr_nnewSup == NULL ) {
   1070 					pb->pb_op->orr_nnewSup = (struct berval *)pb->pb_op->o_tmpalloc(
   1071 						sizeof(struct berval), pb->pb_op->o_tmpmemctx );
   1072 					BER_BVZERO( pb->pb_op->orr_nnewSup );
   1073 				}
   1074 				rc = pblock_set_dn( value, pb->pb_op->orr_newSup, pb->pb_op->orr_nnewSup, pb->pb_op->o_tmpmemctx );
   1075 				if ( rc == LDAP_SUCCESS ) {
   1076 					build_new_dn( &pb->pb_op->orr_newDN, pb->pb_op->orr_newSup, &pb->pb_op->orr_newrdn, pb->pb_op->o_tmpmemctx );
   1077 					build_new_dn( &pb->pb_op->orr_nnewDN, pb->pb_op->orr_nnewSup, &pb->pb_op->orr_nnewrdn, pb->pb_op->o_tmpmemctx );
   1078 				}
   1079 			}
   1080 		} else {
   1081 			rc = PBLOCK_ERROR;
   1082 		}
   1083 		break;
   1084 	case SLAPI_MODRDN_DELOLDRDN:
   1085 		PBLOCK_ASSERT_OP( pb, 0 );
   1086 		PBLOCK_VALIDATE_IS_INTOP( pb );
   1087 		if ( pb->pb_op->o_tag == LDAP_REQ_MODRDN )
   1088 			pb->pb_op->orr_deleteoldrdn = *((int *)value);
   1089 		else
   1090 			rc = PBLOCK_ERROR;
   1091 		break;
   1092 	case SLAPI_SEARCH_SCOPE: {
   1093 		int scope = *((int *)value);
   1094 
   1095 		PBLOCK_ASSERT_OP( pb, 0 );
   1096 		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH ) {
   1097 			switch ( *((int *)value) ) {
   1098 			case LDAP_SCOPE_BASE:
   1099 			case LDAP_SCOPE_ONELEVEL:
   1100 			case LDAP_SCOPE_SUBTREE:
   1101 			case LDAP_SCOPE_SUBORDINATE:
   1102 				pb->pb_op->ors_scope = scope;
   1103 				break;
   1104 			default:
   1105 				rc = PBLOCK_ERROR;
   1106 				break;
   1107 			}
   1108 		} else {
   1109 			rc = PBLOCK_ERROR;
   1110 		}
   1111 		break;
   1112 	}
   1113 	case SLAPI_SEARCH_DEREF:
   1114 		PBLOCK_ASSERT_OP( pb, 0 );
   1115 		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
   1116 			pb->pb_op->ors_deref = *((int *)value);
   1117 		else
   1118 			rc = PBLOCK_ERROR;
   1119 		break;
   1120 	case SLAPI_SEARCH_SIZELIMIT:
   1121 		PBLOCK_ASSERT_OP( pb, 0 );
   1122 		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
   1123 			pb->pb_op->ors_slimit = *((int *)value);
   1124 		else
   1125 			rc = PBLOCK_ERROR;
   1126 		break;
   1127 	case SLAPI_SEARCH_TIMELIMIT:
   1128 		PBLOCK_ASSERT_OP( pb, 0 );
   1129 		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
   1130 			pb->pb_op->ors_tlimit = *((int *)value);
   1131 		else
   1132 			rc = PBLOCK_ERROR;
   1133 		break;
   1134 	case SLAPI_SEARCH_FILTER:
   1135 		PBLOCK_ASSERT_OP( pb, 0 );
   1136 		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
   1137 			pb->pb_op->ors_filter = (Slapi_Filter *)value;
   1138 		else
   1139 			rc = PBLOCK_ERROR;
   1140 		break;
   1141 	case SLAPI_SEARCH_STRFILTER:
   1142 		PBLOCK_ASSERT_OP( pb, 0 );
   1143 		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH ) {
   1144 			pb->pb_op->ors_filterstr.bv_val = (char *)value;
   1145 			pb->pb_op->ors_filterstr.bv_len = strlen((char *)value);
   1146 		} else {
   1147 			rc = PBLOCK_ERROR;
   1148 		}
   1149 		break;
   1150 	case SLAPI_SEARCH_ATTRS: {
   1151 		AttributeName *an = NULL;
   1152 		size_t i = 0, j = 0;
   1153 		char **attrs = (char **)value;
   1154 
   1155 		PBLOCK_ASSERT_OP( pb, 0 );
   1156 		PBLOCK_VALIDATE_IS_INTOP( pb );
   1157 
   1158 		if ( pb->pb_op->o_tag != LDAP_REQ_SEARCH ) {
   1159 			rc = PBLOCK_ERROR;
   1160 			break;
   1161 		}
   1162 		/* also set mapped attrs */
   1163 		rc = pblock_set_default( pb, param, value );
   1164 		if ( rc != PBLOCK_SUCCESS ) {
   1165 			break;
   1166 		}
   1167 		if ( pb->pb_op->ors_attrs != NULL ) {
   1168 			pb->pb_op->o_tmpfree( pb->pb_op->ors_attrs, pb->pb_op->o_tmpmemctx );
   1169 			pb->pb_op->ors_attrs = NULL;
   1170 		}
   1171 		if ( attrs != NULL ) {
   1172 			for ( i = 0; attrs[i] != NULL; i++ )
   1173 				;
   1174 		}
   1175 		if ( i ) {
   1176 			an = (AttributeName *)pb->pb_op->o_tmpcalloc( i + 1,
   1177 				sizeof(AttributeName), pb->pb_op->o_tmpmemctx );
   1178 			for ( i = 0; attrs[i] != NULL; i++ ) {
   1179 				an[j].an_desc = NULL;
   1180 				an[j].an_oc = NULL;
   1181 				an[j].an_flags = 0;
   1182 				an[j].an_name.bv_val = attrs[i];
   1183 				an[j].an_name.bv_len = strlen( attrs[i] );
   1184 				if ( slap_bv2ad( &an[j].an_name, &an[j].an_desc, &pb->pb_rs->sr_text ) == LDAP_SUCCESS ) {
   1185 					j++;
   1186 				}
   1187 			}
   1188 			an[j].an_name.bv_val = NULL;
   1189 			an[j].an_name.bv_len = 0;
   1190 		}
   1191 		pb->pb_op->ors_attrs = an;
   1192 		break;
   1193 	}
   1194 	case SLAPI_SEARCH_ATTRSONLY:
   1195 		PBLOCK_ASSERT_OP( pb, 0 );
   1196 		PBLOCK_VALIDATE_IS_INTOP( pb );
   1197 
   1198 		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
   1199 			pb->pb_op->ors_attrsonly = *((int *)value);
   1200 		else
   1201 			rc = PBLOCK_ERROR;
   1202 		break;
   1203 	case SLAPI_SEARCH_RESULT_ENTRY:
   1204 		PBLOCK_ASSERT_OP( pb, 0 );
   1205 		rs_replace_entry( pb->pb_op, pb->pb_rs, NULL, (Slapi_Entry *)value );
   1206 		/* TODO: Should REP_ENTRY_MODIFIABLE be set? */
   1207 		pb->pb_rs->sr_flags |= REP_ENTRY_MUSTBEFREED;
   1208 		break;
   1209 	case SLAPI_BIND_RET_SASLCREDS:
   1210 		PBLOCK_ASSERT_OP( pb, 0 );
   1211 		pb->pb_rs->sr_sasldata = (struct berval *)value;
   1212 		break;
   1213 	case SLAPI_EXT_OP_REQ_OID:
   1214 		PBLOCK_ASSERT_OP( pb, 0 );
   1215 		PBLOCK_VALIDATE_IS_INTOP( pb );
   1216 
   1217 		if ( pb->pb_op->o_tag == LDAP_REQ_EXTENDED ) {
   1218 			pb->pb_op->ore_reqoid.bv_val = (char *)value;
   1219 			pb->pb_op->ore_reqoid.bv_len = strlen((char *)value);
   1220 		} else {
   1221 			rc = PBLOCK_ERROR;
   1222 		}
   1223 		break;
   1224 	case SLAPI_EXT_OP_REQ_VALUE:
   1225 		PBLOCK_ASSERT_OP( pb, 0 );
   1226 		PBLOCK_VALIDATE_IS_INTOP( pb );
   1227 
   1228 		if ( pb->pb_op->o_tag == LDAP_REQ_EXTENDED )
   1229 			pb->pb_op->ore_reqdata = (struct berval *)value;
   1230 		else
   1231 			rc = PBLOCK_ERROR;
   1232 		break;
   1233 	case SLAPI_EXT_OP_RET_OID:
   1234 		PBLOCK_ASSERT_OP( pb, 0 );
   1235 		pb->pb_rs->sr_rspoid = (char *)value;
   1236 		break;
   1237 	case SLAPI_EXT_OP_RET_VALUE:
   1238 		PBLOCK_ASSERT_OP( pb, 0 );
   1239 		pb->pb_rs->sr_rspdata = (struct berval *)value;
   1240 		break;
   1241 	case SLAPI_BIND_METHOD:
   1242 		PBLOCK_ASSERT_OP( pb, 0 );
   1243 		PBLOCK_VALIDATE_IS_INTOP( pb );
   1244 
   1245 		if ( pb->pb_op->o_tag == LDAP_REQ_BIND )
   1246 			pb->pb_op->orb_method = *((int *)value);
   1247 		else
   1248 			rc = PBLOCK_ERROR;
   1249 		break;
   1250 	case SLAPI_BIND_CREDENTIALS:
   1251 		PBLOCK_ASSERT_OP( pb, 0 );
   1252 		PBLOCK_VALIDATE_IS_INTOP( pb );
   1253 
   1254 		if ( pb->pb_op->o_tag == LDAP_REQ_BIND )
   1255 			pb->pb_op->orb_cred = *((struct berval *)value);
   1256 		else
   1257 			rc = PBLOCK_ERROR;
   1258 		break;
   1259 	case SLAPI_COMPARE_TYPE:
   1260 		PBLOCK_ASSERT_OP( pb, 0 );
   1261 		PBLOCK_VALIDATE_IS_INTOP( pb );
   1262 
   1263 		if ( pb->pb_op->o_tag == LDAP_REQ_COMPARE ) {
   1264 			const char *text;
   1265 
   1266 			pb->pb_op->orc_ava->aa_desc = NULL;
   1267 			rc = slap_str2ad( (char *)value, &pb->pb_op->orc_ava->aa_desc, &text );
   1268 		} else {
   1269 			rc = PBLOCK_ERROR;
   1270 		}
   1271 		break;
   1272 	case SLAPI_COMPARE_VALUE:
   1273 		PBLOCK_ASSERT_OP( pb, 0 );
   1274 		PBLOCK_VALIDATE_IS_INTOP( pb );
   1275 
   1276 		if ( pb->pb_op->o_tag == LDAP_REQ_COMPARE )
   1277 			pb->pb_op->orc_ava->aa_value = *((struct berval *)value);
   1278 		else
   1279 			rc = PBLOCK_ERROR;
   1280 		break;
   1281 	case SLAPI_ABANDON_MSGID:
   1282 		PBLOCK_ASSERT_OP( pb, 0 );
   1283 		PBLOCK_VALIDATE_IS_INTOP( pb );
   1284 
   1285 		if ( pb->pb_op->o_tag == LDAP_REQ_ABANDON)
   1286 			pb->pb_op->orn_msgid = *((int *)value);
   1287 		else
   1288 			rc = PBLOCK_ERROR;
   1289 		break;
   1290 	case SLAPI_REQUESTOR_ISROOT:
   1291 	case SLAPI_IS_REPLICATED_OPERATION:
   1292 	case SLAPI_CONN_AUTHTYPE:
   1293 	case SLAPI_CONN_AUTHMETHOD:
   1294 	case SLAPI_IS_INTERNAL_OPERATION:
   1295 	case SLAPI_X_CONN_IS_UDP:
   1296 	case SLAPI_CONN_CLIENTIP:
   1297 	case SLAPI_X_CONN_CLIENTPATH:
   1298 	case SLAPI_CONN_SERVERIP:
   1299 	case SLAPI_X_CONN_SERVERPATH:
   1300 	case SLAPI_X_ADD_STRUCTURAL_CLASS:
   1301 		/* These parameters cannot be set */
   1302 		rc = PBLOCK_ERROR;
   1303 		break;
   1304 	default:
   1305 		rc = pblock_set_default( pb, param, value );
   1306 		break;
   1307 	}
   1308 
   1309 	pblock_unlock( pb );
   1310 
   1311 	return rc;
   1312 }
   1313 
   1314 static void
   1315 pblock_clear( Slapi_PBlock *pb )
   1316 {
   1317 	pb->pb_nParams = 1;
   1318 }
   1319 
   1320 static int
   1321 pblock_delete_param( Slapi_PBlock *p, int param )
   1322 {
   1323 	int i;
   1324 
   1325 	pblock_lock(p);
   1326 
   1327 	for ( i = 0; i < p->pb_nParams; i++ ) {
   1328 		if ( p->pb_params[i] == param ) {
   1329 			break;
   1330 		}
   1331 	}
   1332 
   1333 	if (i >= p->pb_nParams ) {
   1334 		pblock_unlock( p );
   1335 		return PBLOCK_ERROR;
   1336 	}
   1337 
   1338 	/* move last parameter to index of deleted parameter */
   1339 	if ( p->pb_nParams > 1 ) {
   1340 		p->pb_params[i] = p->pb_params[p->pb_nParams - 1];
   1341 		p->pb_values[i] = p->pb_values[p->pb_nParams - 1];
   1342 	}
   1343 	p->pb_nParams--;
   1344 
   1345 	pblock_unlock( p );
   1346 
   1347 	return PBLOCK_SUCCESS;
   1348 }
   1349 
   1350 Slapi_PBlock *
   1351 slapi_pblock_new(void)
   1352 {
   1353 	Slapi_PBlock *pb;
   1354 
   1355 	pb = (Slapi_PBlock *) ch_calloc( 1, sizeof(Slapi_PBlock) );
   1356 	if ( pb != NULL ) {
   1357 		ldap_pvt_thread_mutex_init( &pb->pb_mutex );
   1358 
   1359 		pb->pb_params[0] = SLAPI_IBM_PBLOCK;
   1360 		pb->pb_values[0].pv_pointer = NULL;
   1361 		pb->pb_nParams = 1;
   1362 		pb->pb_conn = NULL;
   1363 		pb->pb_op = NULL;
   1364 		pb->pb_rs = NULL;
   1365 		pb->pb_intop = 0;
   1366 	}
   1367 	return pb;
   1368 }
   1369 
   1370 static void
   1371 pblock_destroy( Slapi_PBlock *pb )
   1372 {
   1373 	LDAPControl **controls = NULL;
   1374 	LDAPMod **mods = NULL;
   1375 	char **attrs = NULL;
   1376 
   1377 	assert( pb != NULL );
   1378 
   1379 	pblock_get_default( pb, SLAPI_RESCONTROLS, (void **)&controls );
   1380 	if ( controls != NULL ) {
   1381 		ldap_controls_free( controls );
   1382 	}
   1383 
   1384 	if ( pb->pb_intop ) {
   1385 		slapi_int_connection_done_pb( pb );
   1386 	} else {
   1387 		pblock_get_default( pb, SLAPI_MODIFY_MODS, (void **)&mods );
   1388 		ldap_mods_free( mods, 1 );
   1389 
   1390 		pblock_get_default( pb, SLAPI_SEARCH_ATTRS, (void **)&attrs );
   1391 		if ( attrs != NULL )
   1392 			pb->pb_op->o_tmpfree( attrs, pb->pb_op->o_tmpmemctx );
   1393 	}
   1394 
   1395 	ldap_pvt_thread_mutex_destroy( &pb->pb_mutex );
   1396 	slapi_ch_free( (void **)&pb );
   1397 }
   1398 
   1399 void
   1400 slapi_pblock_destroy( Slapi_PBlock *pb )
   1401 {
   1402 	if ( pb != NULL ) {
   1403 		pblock_destroy( pb );
   1404 	}
   1405 }
   1406 
   1407 int
   1408 slapi_pblock_get( Slapi_PBlock *pb, int arg, void *value )
   1409 {
   1410 	return pblock_get( pb, arg, (void **)value );
   1411 }
   1412 
   1413 int
   1414 slapi_pblock_set( Slapi_PBlock *pb, int arg, void *value )
   1415 {
   1416 	return pblock_set( pb, arg, value );
   1417 }
   1418 
   1419 void
   1420 slapi_pblock_clear( Slapi_PBlock *pb )
   1421 {
   1422 	pblock_clear( pb );
   1423 }
   1424 
   1425 int
   1426 slapi_pblock_delete_param( Slapi_PBlock *p, int param )
   1427 {
   1428 	return pblock_delete_param( p, param );
   1429 }
   1430 
   1431 /*
   1432  * OpenLDAP extension
   1433  */
   1434 int
   1435 slapi_int_pblock_get_first( Backend *be, Slapi_PBlock **pb )
   1436 {
   1437 	assert( pb != NULL );
   1438 	*pb = SLAPI_BACKEND_PBLOCK( be );
   1439 	return (*pb == NULL ? LDAP_OTHER : LDAP_SUCCESS);
   1440 }
   1441 
   1442 /*
   1443  * OpenLDAP extension
   1444  */
   1445 int
   1446 slapi_int_pblock_get_next( Slapi_PBlock **pb )
   1447 {
   1448 	assert( pb != NULL );
   1449 	return slapi_pblock_get( *pb, SLAPI_IBM_PBLOCK, pb );
   1450 }
   1451 
   1452 #endif /* LDAP_SLAPI */
   1453