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