From 1b70e1644888c477890722e45307fea60eaa3d77 Mon Sep 17 00:00:00 2001
From: Pierangelo Masarati <ando@openldap.org>
Date: Sat, 7 Dec 2002 17:19:29 +0000
Subject: [PATCH] SLAPI - Netscape plugin API for slapd - based on patch
 contributed by Steve Omrani <somrani@us.ibm.com> as ITS#2073

---
 configure.in                            |   36 +
 include/slapi-plugin.h                  |  370 +++++++
 servers/slapd/Makefile.in               |   25 +-
 servers/slapd/add.c                     |   56 +-
 servers/slapd/backend.c                 |   48 +-
 servers/slapd/bind.c                    |   45 +
 servers/slapd/compare.c                 |   47 +
 servers/slapd/config.c                  |   45 +
 servers/slapd/connection.c              |   18 +-
 servers/slapd/controls.c                |    6 +
 servers/slapd/delete.c                  |   45 +
 servers/slapd/extended.c                |   90 +-
 servers/slapd/main.c                    |   17 +
 servers/slapd/modify.c                  |   45 +
 servers/slapd/modrdn.c                  |   49 +
 servers/slapd/operation.c               |   12 +
 servers/slapd/proto-slap.h              |   20 +-
 servers/slapd/result.c                  |   10 +-
 servers/slapd/root_dse.c                |   13 +
 servers/slapd/search.c                  |   52 +
 servers/slapd/slap.h                    |   93 ++
 servers/slapd/slapi/Makefile.in         |   45 +
 servers/slapd/slapi/README              |   55 +
 servers/slapd/slapi/ibm_pblock_params.h |   68 ++
 servers/slapd/slapi/plugin.c            |  679 ++++++++++++
 servers/slapd/slapi/plugin.h            |   28 +
 servers/slapd/slapi/printmsg.c          |  118 ++
 servers/slapd/slapi/slapi-plugin.h      |  379 +++++++
 servers/slapd/slapi/slapi.h             |  296 +++++
 servers/slapd/slapi/slapi_cl.h          |   55 +
 servers/slapd/slapi/slapi_common.h      |   40 +
 servers/slapd/slapi/slapi_ops.c         | 1269 ++++++++++++++++++++++
 servers/slapd/slapi/slapi_ops.c.all     | 1303 +++++++++++++++++++++++
 servers/slapd/slapi/slapi_ops.c.save    | 1271 ++++++++++++++++++++++
 servers/slapd/slapi/slapi_ops.h         |   34 +
 servers/slapd/slapi/slapi_pblock.c      |  436 ++++++++
 servers/slapd/slapi/slapi_pblock.h      |   40 +
 servers/slapd/slapi/slapi_utils.c       | 1132 ++++++++++++++++++++
 servers/slapd/slapi/slapi_utils.h       |  115 ++
 servers/slapd/tools/Makefile.in         |    3 +-
 servers/slapd/tools/mimic.c             |   22 +-
 41 files changed, 8473 insertions(+), 57 deletions(-)
 create mode 100644 include/slapi-plugin.h
 create mode 100644 servers/slapd/slapi/Makefile.in
 create mode 100644 servers/slapd/slapi/README
 create mode 100644 servers/slapd/slapi/ibm_pblock_params.h
 create mode 100644 servers/slapd/slapi/plugin.c
 create mode 100644 servers/slapd/slapi/plugin.h
 create mode 100644 servers/slapd/slapi/printmsg.c
 create mode 100644 servers/slapd/slapi/slapi-plugin.h
 create mode 100644 servers/slapd/slapi/slapi.h
 create mode 100644 servers/slapd/slapi/slapi_cl.h
 create mode 100644 servers/slapd/slapi/slapi_common.h
 create mode 100644 servers/slapd/slapi/slapi_ops.c
 create mode 100644 servers/slapd/slapi/slapi_ops.c.all
 create mode 100644 servers/slapd/slapi/slapi_ops.c.save
 create mode 100644 servers/slapd/slapi/slapi_ops.h
 create mode 100644 servers/slapd/slapi/slapi_pblock.c
 create mode 100644 servers/slapd/slapi/slapi_pblock.h
 create mode 100644 servers/slapd/slapi/slapi_utils.c
 create mode 100644 servers/slapd/slapi/slapi_utils.h

diff --git a/configure.in b/configure.in
index e0594ebed2..464d36f6d6 100644
--- a/configure.in
+++ b/configure.in
@@ -186,6 +186,8 @@ OL_ARG_ENABLE(rlookups,[    --enable-rlookups	  enable reverse lookups of client
 OL_ARG_ENABLE(slp, [    --enable-slp          enable SLPv2 support], no)dnl     
 OL_ARG_ENABLE(wrappers,[    --enable-wrappers	  enable tcp wrapper support], no)dnl
 
+OL_ARG_ENABLE(slapi,[    --enable-slapi   enable installation of slapi library], yes)dnl
+
 dnl SLAPD Backend options
 OL_ARG_ENABLE(bdb,[    --enable-bdb	  enable Berkeley DB backend], yes)dnl
 OL_ARG_WITH(bdb_module,[    --with-bdb-module     module type static|dynamic], static,
@@ -247,6 +249,9 @@ dnl General "enable" options
 # validate options
 if test $ol_enable_slapd = no ; then
 	dnl SLAPD was specificallly disabled
+	if test $ol_enable_slapi = yes ; then
+		AC_MSG_WARN([slapd disabled, ignoring --enable-slapi argument])
+	fi
 	if test $ol_enable_bdb = yes ; then
 		AC_MSG_WARN([slapd disabled, ignoring --enable-bdb argument])
 	fi
@@ -351,6 +356,7 @@ if test $ol_enable_slapd = no ; then
 	fi
 
 	# force settings to no
+	ol_enable_slapi=no
 	ol_enable_bdb=no
 	ol_enable_dnssrv=no
 	ol_enable_ldap=no
@@ -521,6 +527,9 @@ BUILD_SLURPD=no
 
 BUILD_THREAD=no
 
+BUILD_SLAPI=no
+SLAPD_SLAPI_DEPEND=
+
 BUILD_BDB=no
 BUILD_DNSSRV=no
 BUILD_LDAP=no
@@ -569,6 +578,7 @@ SASL_LIBS=
 TERMCAP_LIBS=
 TLS_LIBS=
 MODULES_LIBS=
+SLAPI_LIBS=
 AUTH_LIBS=
 
 SLAPD_SLP_LIBS=
@@ -2504,6 +2514,22 @@ OL_SYS_ERRLIST
 dnl ----------------------------------------------------------------
 dnl Sort out defines
 
+if test "$ol_enable_slapi" != no ; then
+	dnl This check is donel also if --enable-modules is used;
+	dnl it is duplicated here, 'cause it'd be cached anyway
+	AC_CHECK_HEADERS(ltdl.h)
+
+	if test $ac_cv_header_ltdl_h != yes ; then
+		AC_MSG_ERROR([could not locate <ltdl.h>])
+	fi
+	AC_CHECK_LIB(ltdl, lt_dlinit, [
+		SLAPI_LIBS=-lltdl
+		AC_DEFINE(HAVE_LIBLTDL,1,[define if you have libtool -ltdl])
+	],[AC_MSG_ERROR([could not locate libtool -lltdl])])
+
+	AC_DEFINE(LDAP_SLAPI,1, [define this to add SLAPI code])
+fi
+
 if test "$ol_enable_debug" != no ; then
 	AC_DEFINE(LDAP_DEBUG,1,
 		[define this to add debugging code])
@@ -2764,6 +2790,12 @@ if test "$ol_enable_rewrite" != no ; then
 	BUILD_REWRITE=yes
 fi
 
+if test "$ol_enable_slapi" != no ; then
+	AC_DEFINE(ENABLE_SLAPI,1,[define to enable slapi library])
+	BUILD_SLAPI=yes
+	SLAPD_SLAPI_DEPEND=libslapi.a
+fi
+
 dnl ----------------------------------------------------------------
 
 dnl
@@ -2789,6 +2821,8 @@ AC_SUBST(PLAT)
 AC_SUBST(BUILD_LIBS_DYNAMIC)
 
 AC_SUBST(BUILD_SLAPD)
+  AC_SUBST(BUILD_SLAPI)
+  AC_SUBST(SLAPD_SLAPI_DEPEND)
   AC_SUBST(BUILD_BDB)
   AC_SUBST(BUILD_DNSSRV)
   AC_SUBST(BUILD_LDAP)
@@ -2843,6 +2877,7 @@ AC_SUBST(SASL_LIBS)
 AC_SUBST(TERMCAP_LIBS)
 AC_SUBST(TLS_LIBS)
 AC_SUBST(MODULES_LIBS)
+AC_SUBST(SLAPI_LIBS)
 AC_SUBST(AUTH_LIBS)
 
 AC_SUBST(SLAPD_SLP_LIBS)
@@ -2896,6 +2931,7 @@ servers/slapd/back-shell/Makefile:build/top.mk:servers/slapd/back-shell/Makefile
 servers/slapd/back-sql/Makefile:build/top.mk:servers/slapd/back-sql/Makefile.in:build/mod.mk \
 servers/slapd/back-tcl/Makefile:build/top.mk:servers/slapd/back-tcl/Makefile.in:build/mod.mk \
 servers/slapd/shell-backends/Makefile:build/top.mk:servers/slapd/shell-backends/Makefile.in:build/srv.mk \
+servers/slapd/slapi/Makefile:build/top.mk:servers/slapd/slapi/Makefile.in:build/lib.mk:build/lib-shared.mk  \
 servers/slapd/tools/Makefile:build/top.mk:servers/slapd/tools/Makefile.in \
 servers/slurpd/Makefile:build/top.mk:servers/slurpd/Makefile.in:build/srv.mk \
 tests/Makefile:build/top.mk:tests/Makefile.in:build/dir.mk \
diff --git a/include/slapi-plugin.h b/include/slapi-plugin.h
new file mode 100644
index 0000000000..cbded3a4bd
--- /dev/null
+++ b/include/slapi-plugin.h
@@ -0,0 +1,370 @@
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ * (C) Copyright IBM Corp. 1997,2002
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is
+ * given to IBM Corporation. This software is provided ``as is''
+ * without express or implied warranty.
+ */
+
+#ifndef _SLAPI_PLUGIN_H
+#define _SLAPI_PLUGIN_H
+
+#include "lber.h"
+#include "ldap.h"
+
+typedef struct slapi_pblock	Slapi_PBlock;
+typedef struct slapi_entry	Slapi_Entry;
+typedef struct slapi_attr	Slapi_Attr;
+typedef struct slapi_filter	Slapi_Filter;
+
+
+/* pblock routines */
+int slapi_pblock_get( Slapi_PBlock *pb, int arg, void *value );
+int slapi_pblock_set( Slapi_PBlock *pb, int arg, void *value );
+Slapi_PBlock *slapi_pblock_new();
+void slapi_pblock_destroy( Slapi_PBlock* );
+
+/*entry/attr/dn routines */
+Slapi_Entry *slapi_str2entry( char *s, int flags );
+char *slapi_entry2str( Slapi_Entry *e, int *len );
+char *slapi_entry_get_dn( Slapi_Entry *e );
+void slapi_entry_set_dn(Slapi_Entry *e, char *dn);
+Slapi_Entry *slapi_entry_dup(Slapi_Entry *e);
+int slapi_entry_attr_delete( Slapi_Entry *e, char *type );
+Slapi_Entry *slapi_entry_alloc();
+void slapi_entry_free( Slapi_Entry *e );
+int slapi_entry_attr_merge( Slapi_Entry *e, char *type, struct berval **vals );
+int slapi_entry_attr_find( Slapi_Entry *e, char *type, Slapi_Attr **attr );
+int slapi_attr_get_values( Slapi_Attr *attr, struct berval ***vals );
+char *slapi_dn_normalize( char *dn );
+char *slapi_dn_normalize_case( char *dn );
+int slapi_dn_issuffix( char *dn, char *suffix );
+char *slapi_dn_ignore_case( char *dn );
+
+/* char routines */
+char * slapi_ch_malloc( unsigned long size );
+void slapi_ch_free( void *ptr );
+char *slapi_ch_calloc( unsigned long nelem, unsigned long size );
+char *slapi_ch_realloc(char *block, unsigned long size );
+char *slapi_ch_strdup(char *s );
+
+
+/* LDAP V3 routines */
+int slapi_control_present( LDAPControl **controls, char *oid, struct berval **val, int *iscritical);
+void slapi_register_supported_control(char *controloid, unsigned long controlops);
+#define SLAPI_OPERATION_BIND            0x00000001L
+#define SLAPI_OPERATION_UNBIND          0x00000002L
+#define SLAPI_OPERATION_SEARCH          0x00000004L
+#define SLAPI_OPERATION_MODIFY          0x00000008L
+#define SLAPI_OPERATION_ADD             0x00000010L
+#define SLAPI_OPERATION_DELETE          0x00000020L
+#define SLAPI_OPERATION_MODDN           0x00000040L
+#define SLAPI_OPERATION_MODRDN          SLAPI_OPERATION_MODDN
+#define SLAPI_OPERATION_COMPARE         0x00000080L
+#define SLAPI_OPERATION_ABANDON         0x00000100L
+#define SLAPI_OPERATION_EXTENDED        0x00000200L
+#define SLAPI_OPERATION_ANY             0xFFFFFFFFL
+#define SLAPI_OPERATION_NONE            0x00000000L
+int slapi_get_supported_controls(char ***ctrloidsp, unsigned long **ctrlopsp);
+void slapi_register_supported_saslmechanism(char *mechanism);
+char **slapi_get_supported_saslmechanisms();
+char **slapi_get_supported_extended_ops(void);
+
+
+/* send ldap result back */
+void slapi_send_ldap_result( Slapi_PBlock *pb, int err, char *matched, char *text, 
+					   int nentries, struct berval **urls );
+int slapi_send_ldap_search_entry( Slapi_PBlock *pb, Slapi_Entry *e, LDAPControl **ectrls,
+                                  char **attrs, int attrsonly );
+
+/* filter routines */
+Slapi_Filter *slapi_str2filter( char *str );
+void slapi_filter_free( Slapi_Filter *f, int recurse );
+int slapi_filter_get_choice( Slapi_Filter *f);
+int slapi_filter_get_ava( Slapi_Filter *f, char **type, struct berval **bval );
+Slapi_Filter *slapi_filter_list_first( Slapi_Filter *f );
+Slapi_Filter *slapi_filter_list_next( Slapi_Filter *f, Slapi_Filter *fprev );
+
+/* internal add/delete/search/modify routines */
+Slapi_PBlock *slapi_search_internal( char *base, int scope, char *filter, 
+	LDAPControl **controls, char **attrs, int attrsonly );
+Slapi_PBlock *slapi_modify_internal( char *dn, LDAPMod **mods,
+        LDAPControl **controls, int log_change);
+Slapi_PBlock *slapi_add_entry_internal( Slapi_Entry * e, LDAPControl **controls, int log_change );
+Slapi_PBlock *slapi_add_internal( char * dn, LDAPMod **attrs, LDAPControl **controls, int log_changes );
+Slapi_PBlock *slapi_add_entry_internal( Slapi_Entry * e, LDAPControl **controls, int log_change );
+Slapi_PBlock *slapi_delete_internal( char * dn,  LDAPControl **controls, int log_change );
+Slapi_PBlock *slapi_modrdn_internal( char * olddn, char * newrdn, char *newParent, int deloldrdn, LDAPControl **controls, int log_change);
+void slapi_free_search_results_internal(Slapi_PBlock *pb);
+
+/* connection related routines */
+int slapi_is_connection_ssl(Slapi_PBlock *pPB, int *isSSL);
+int slapi_get_client_port(Slapi_PBlock *pPB, int *fromPort);
+
+/* parameters currently supported */
+
+
+/* plugin types supported */
+
+#define SLAPI_PLUGIN_DATABASE           1
+#define SLAPI_PLUGIN_EXTENDEDOP         2
+#define SLAPI_PLUGIN_PREOPERATION       3
+#define SLAPI_PLUGIN_POSTOPERATION      4
+#define SLAPI_PLUGIN_AUDIT              7   
+
+/* misc params */
+
+#define SLAPI_BACKEND				130
+#define SLAPI_CONNECTION			131
+#define SLAPI_OPERATION				132
+#define SLAPI_REQUESTOR_ISROOT			133
+#define SLAPI_BE_MONITORDN			134
+#define SLAPI_BE_TYPE           		135
+#define SLAPI_BE_READONLY       		136
+#define SLAPI_BE_LASTMOD       			137
+#define SLAPI_CONN_ID        			139
+
+/* operation params */
+#define SLAPI_OPINITIATED_TIME			140
+#define SLAPI_REQUESTOR_DN			141
+#define SLAPI_REQUESTOR_ISUPDATEDN		142
+
+/* connection  structure params*/
+#define SLAPI_CONN_DN        			143
+#define SLAPI_CONN_AUTHTYPE    			144
+
+/*  Authentication types */
+#define SLAPD_AUTH_NONE   "none"
+#define SLAPD_AUTH_SIMPLE "simple"
+#define SLAPD_AUTH_SSL    "SSL"
+#define SLAPD_AUTH_SASL   "SASL " 
+
+/* plugin configuration parmams */
+#define SLAPI_PLUGIN				3
+#define SLAPI_PLUGIN_PRIVATE			4
+#define SLAPI_PLUGIN_TYPE			5
+#define SLAPI_PLUGIN_ARGV			6
+#define SLAPI_PLUGIN_ARGC			7
+#define SLAPI_PLUGIN_VERSION			8
+#define SLAPI_PLUGIN_OPRETURN			9
+#define SLAPI_PLUGIN_OBJECT			10
+#define SLAPI_PLUGIN_DESTROY_FN			11
+#define SLAPI_PLUGIN_DESCRIPTION		12
+
+/* internal opreations params */
+#define SLAPI_PLUGIN_INTOP_RESULT		15
+#define SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES	16
+#define SLAPI_PLUGIN_INTOP_SEARCH_REFERRALS	17
+
+/* function pointer params for backends */
+#define SLAPI_PLUGIN_DB_BIND_FN			200
+#define SLAPI_PLUGIN_DB_UNBIND_FN		201
+#define SLAPI_PLUGIN_DB_SEARCH_FN		202
+#define SLAPI_PLUGIN_DB_COMPARE_FN		203
+#define SLAPI_PLUGIN_DB_MODIFY_FN		204
+#define SLAPI_PLUGIN_DB_MODRDN_FN		205
+#define SLAPI_PLUGIN_DB_ADD_FN			206
+#define SLAPI_PLUGIN_DB_DELETE_FN		207
+#define SLAPI_PLUGIN_DB_ABANDON_FN		208
+#define SLAPI_PLUGIN_DB_CONFIG_FN		209
+#define SLAPI_PLUGIN_CLOSE_FN			210
+#define SLAPI_PLUGIN_DB_FLUSH_FN		211
+#define SLAPI_PLUGIN_START_FN			212
+#define SLAPI_PLUGIN_DB_SEQ_FN			213
+#define SLAPI_PLUGIN_DB_ENTRY_FN		214
+#define SLAPI_PLUGIN_DB_REFERRAL_FN		215
+#define SLAPI_PLUGIN_DB_RESULT_FN		216
+#define SLAPI_PLUGIN_DB_LDIF2DB_FN		217
+#define SLAPI_PLUGIN_DB_DB2LDIF_FN		218
+#define SLAPI_PLUGIN_DB_BEGIN_FN		219
+#define SLAPI_PLUGIN_DB_COMMIT_FN		220
+#define SLAPI_PLUGIN_DB_ABORT_FN		221
+#define SLAPI_PLUGIN_DB_ARCHIVE2DB_FN		222
+#define SLAPI_PLUGIN_DB_DB2ARCHIVE_FN		223
+#define SLAPI_PLUGIN_DB_NEXT_SEARCH_ENTRY_FN	224
+#define SLAPI_PLUGIN_DB_FREE_RESULT_SET_FN	225
+#define	SLAPI_PLUGIN_DB_SIZE_FN			226
+#define	SLAPI_PLUGIN_DB_TEST_FN			227
+
+
+/*  functions pointers for LDAP V3 extended ops */
+#define SLAPI_PLUGIN_EXT_OP_FN			300
+#define SLAPI_PLUGIN_EXT_OP_OIDLIST		301
+
+/* functions for preoperation functions */
+#define SLAPI_PLUGIN_PRE_BIND_FN		401
+#define SLAPI_PLUGIN_PRE_UNBIND_FN		402
+#define SLAPI_PLUGIN_PRE_SEARCH_FN		403
+#define SLAPI_PLUGIN_PRE_COMPARE_FN		404
+#define SLAPI_PLUGIN_PRE_MODIFY_FN		405
+#define SLAPI_PLUGIN_PRE_MODRDN_FN		406
+#define SLAPI_PLUGIN_PRE_ADD_FN			407
+#define SLAPI_PLUGIN_PRE_DELETE_FN		408
+#define SLAPI_PLUGIN_PRE_ABANDON_FN		409
+#define SLAPI_PLUGIN_PRE_ENTRY_FN		410
+#define SLAPI_PLUGIN_PRE_REFERRAL_FN		411
+#define SLAPI_PLUGIN_PRE_RESULT_FN		412
+
+/*  functions for postoperation functions*/
+#define SLAPI_PLUGIN_POST_BIND_FN		501
+#define SLAPI_PLUGIN_POST_UNBIND_FN		502
+#define SLAPI_PLUGIN_POST_SEARCH_FN		503
+#define SLAPI_PLUGIN_POST_COMPARE_FN		504
+#define SLAPI_PLUGIN_POST_MODIFY_FN		505
+#define SLAPI_PLUGIN_POST_MODRDN_FN		506
+#define SLAPI_PLUGIN_POST_ADD_FN		507
+#define SLAPI_PLUGIN_POST_DELETE_FN		508
+#define SLAPI_PLUGIN_POST_ABANDON_FN		509
+#define SLAPI_PLUGIN_POST_ENTRY_FN		510
+#define SLAPI_PLUGIN_POST_REFERRAL_FN		511
+#define SLAPI_PLUGIN_POST_RESULT_FN		512
+
+/* audit plugin defines */
+#define SLAPI_PLUGIN_AUDIT_DATA                1100
+#define SLAPI_PLUGIN_AUDIT_FN                  1101
+
+/* managedsait control */
+#define SLAPI_MANAGEDSAIT       		1000
+
+/* config stuff */
+#define SLAPI_CONFIG_FILENAME			40
+#define SLAPI_CONFIG_LINENO			41
+#define SLAPI_CONFIG_ARGC			42
+#define SLAPI_CONFIG_ARGV			43
+
+/*  operational params */
+#define SLAPI_TARGET_DN				50
+#define SLAPI_REQCONTROLS			51
+
+/* server LDAPv3 controls  */
+#define SLAPI_RESCONTROLS			55
+#define SLAPI_ADD_RESCONTROL			56	
+
+/* add params */
+#define SLAPI_ADD_TARGET			SLAPI_TARGET_DN
+#define SLAPI_ADD_ENTRY				60
+
+/* bind params */
+#define SLAPI_BIND_TARGET			SLAPI_TARGET_DN
+#define SLAPI_BIND_METHOD			70
+#define SLAPI_BIND_CREDENTIALS			71	
+#define SLAPI_BIND_SASLMECHANISM		72	
+#define SLAPI_BIND_RET_SASLCREDS		73	
+
+/* compare params */
+#define SLAPI_COMPARE_TARGET			SLAPI_TARGET_DN
+#define SLAPI_COMPARE_TYPE			80
+#define SLAPI_COMPARE_VALUE			81
+
+/* delete params */
+#define SLAPI_DELETE_TARGET			SLAPI_TARGET_DN
+
+/* modify params */
+#define SLAPI_MODIFY_TARGET			SLAPI_TARGET_DN
+#define SLAPI_MODIFY_MODS			90
+
+/* modrdn params */
+#define SLAPI_MODRDN_TARGET			SLAPI_TARGET_DN
+#define SLAPI_MODRDN_NEWRDN			100
+#define SLAPI_MODRDN_DELOLDRDN			101
+#define SLAPI_MODRDN_NEWSUPERIOR		102	/* v3 only */
+
+/* search params */
+#define SLAPI_SEARCH_TARGET			SLAPI_TARGET_DN
+#define SLAPI_SEARCH_SCOPE			110
+#define SLAPI_SEARCH_DEREF			111
+#define SLAPI_SEARCH_SIZELIMIT			112
+#define SLAPI_SEARCH_TIMELIMIT			113
+#define SLAPI_SEARCH_FILTER			114
+#define SLAPI_SEARCH_STRFILTER			115
+#define SLAPI_SEARCH_ATTRS			116
+#define SLAPI_SEARCH_ATTRSONLY			117
+
+/* abandon params */
+#define SLAPI_ABANDON_MSGID			120
+
+/* extended operation params */
+#define SLAPI_EXT_OP_REQ_OID			160
+#define SLAPI_EXT_OP_REQ_VALUE		161	
+
+/* extended operation return codes */
+#define SLAPI_EXT_OP_RET_OID			162	
+#define SLAPI_EXT_OP_RET_VALUE		163	
+
+#define SLAPI_PLUGIN_EXTENDED_SENT_RESULT	-1
+
+/* Search result params */
+#define SLAPI_SEARCH_RESULT_SET			193
+#define	SLAPI_SEARCH_RESULT_ENTRY		194
+#define	SLAPI_NENTRIES				195
+#define SLAPI_SEARCH_REFERRALS			196
+
+
+/* filter types */
+#ifndef LDAP_FILTER_AND
+#define LDAP_FILTER_AND         0xa0L
+#endif
+#ifndef LDAP_FILTER_OR
+#define LDAP_FILTER_OR          0xa1L
+#endif
+#ifndef LDAP_FILTER_NOT
+#define LDAP_FILTER_NOT         0xa2L
+#endif
+#ifndef LDAP_FILTER_EQUALITY
+#define LDAP_FILTER_EQUALITY    0xa3L
+#endif
+#ifndef LDAP_FILTER_SUBSTRINGS
+#define LDAP_FILTER_SUBSTRINGS  0xa4L
+#endif
+#ifndef LDAP_FILTER_GE
+#define LDAP_FILTER_GE          0xa5L
+#endif
+#ifndef LDAP_FILTER_LE
+#define LDAP_FILTER_LE          0xa6L
+#endif
+#ifndef LDAP_FILTER_PRESENT
+#define LDAP_FILTER_PRESENT     0x87L
+#endif
+#ifndef LDAP_FILTER_APPROX
+#define LDAP_FILTER_APPROX      0xa8L
+#endif
+#ifndef LDAP_FILTER_EXT_MATCH
+#define LDAP_FILTER_EXT_MATCH   0xa9L
+#endif
+
+int slapi_log_error( int severity, char *subsystem, char *fmt, ... );
+#define SLAPI_LOG_FATAL                 0
+#define SLAPI_LOG_TRACE                 1
+#define SLAPI_LOG_PACKETS               2
+#define SLAPI_LOG_ARGS                  3
+#define SLAPI_LOG_CONNS                 4
+#define SLAPI_LOG_BER                   5
+#define SLAPI_LOG_FILTER                6
+#define SLAPI_LOG_CONFIG                7
+#define SLAPI_LOG_ACL                   8
+#define SLAPI_LOG_SHELL                 9
+#define SLAPI_LOG_PARSE                 10
+#define SLAPI_LOG_HOUSE                 11
+#define SLAPI_LOG_REPL                  12
+#define SLAPI_LOG_CACHE                 13
+#define SLAPI_LOG_PLUGIN                14
+#define SLAPI_LOG_TIMING                15
+
+#define SLAPI_PLUGIN_DESCRIPTION	12
+typedef struct slapi_plugindesc {
+        char    *spd_id;
+        char    *spd_vendor;
+        char    *spd_version;
+        char    *spd_description;
+} Slapi_PluginDesc;
+
+#define SLAPI_PLUGIN_VERSION_01         "01"
+#define SLAPI_PLUGIN_VERSION_02         "02"
+#define SLAPI_PLUGIN_VERSION_03         "03"
+#define SLAPI_PLUGIN_CURRENT_VERSION    SLAPI_PLUGIN_VERSION_03
+
+#endif
diff --git a/servers/slapd/Makefile.in b/servers/slapd/Makefile.in
index 717b91dc70..4bc2c73142 100644
--- a/servers/slapd/Makefile.in
+++ b/servers/slapd/Makefile.in
@@ -35,11 +35,11 @@ OBJS	= main.o daemon.o connection.o search.o filter.o add.o cr.o \
 		limits.o backglue.o operational.o matchedValues.o \
 		$(@PLAT@_OBJS)
 
-LDAP_INCDIR= ../../include
+LDAP_INCDIR= ../../include -Islapi
 LDAP_LIBDIR= ../../libraries
 
 SLAP_DIR=
-SLAPD_STATIC_DEPENDS=@SLAPD_NO_STATIC@ libbackends.a
+SLAPD_STATIC_DEPENDS=@SLAPD_SLAPI_DEPEND@ @SLAPD_NO_STATIC@ libbackends.a
 SLAPD_STATIC_BACKENDS=@SLAPD_STATIC_BACKENDS@
 SLAPD_DYNAMIC_BACKENDS=@SLAPD_DYNAMIC_BACKENDS@
 
@@ -48,7 +48,7 @@ XLDFLAGS = $(MODULES_LDFLAGS)
 
 XLIBS = $(SLAPD_STATIC_DEPENDS) $(SLAPD_L)
 XXLIBS = $(LDBM_LIBS) $(SLAPD_LIBS) $(SECURITY_LIBS) $(LDIF_LIBS) $(LUTIL_LIBS)
-XXXLIBS = $(LTHREAD_LIBS) $(MODULES_LIBS)
+XXXLIBS = $(LTHREAD_LIBS) $(MODULES_LIBS) $(SLAPI_LIBS)
 
 BUILD_OPT = "--enable-slapd"
 BUILD_SRV = @BUILD_SLAPD@
@@ -224,8 +224,17 @@ slapd.exp: libslapd.a
 	dlltool --dllname slapd.exe --input-def slapd.def \
 		--base-file slapd.base --output-exp $@
 
+.slapi: FORCE
+	(cd slapi; $(MAKE) $(MFLAGS) all)
+
+libslapi.a: .slapi
+	$(AR) ruv slapi/libtmpslapd.a $(OBJS)
+	cp slapi/.libs/libslapi.a .
+
 slapd: $(SLAPD_DEPENDS)
-	$(LTLINK) -o $@ $(SLAPD_OBJECTS) $(LIBS) $(WRAP_LIBS)
+	$(LTLINK) -o $@ $(SLAPD_OBJECTS) $(LIBS) \
+		libslapi.a slapi/libtmpslapd.a \
+		$(WRAP_LIBS)
 
 sslapd: version.o
 	$(LTLINK) -static -o $@ $(OBJS) version.o $(LIBS) $(WRAP_LIBS)
@@ -280,7 +289,7 @@ version.c: $(OBJS) $(SLAPD_LIBDEPEND)
 	$(MKVERSION) -s -n Versionstr slapd > $@
 
 depend-local-srv: FORCE
-	@for i in back-* shell-backends tools; do \
+	@for i in back-* shell-backends slapi tools; do \
 		if test -d $$i -a -f $$i/Makefile ; then \
 			echo; echo "  cd $$i; $(MAKE) $(MFLAGS) depend"; \
 			( cd $$i; $(MAKE) $(MFLAGS) depend ); \
@@ -293,7 +302,7 @@ clean-local:
 	rm -f *.exp *.def *.base *.a *.objs symdummy.c
 
 clean-local-srv: FORCE
-	@for i in back-* shell-backends tools; do \
+	@for i in back-* shell-backends slapi tools; do \
 		if test -d $$i -a -f $$i/Makefile ; then \
 			echo; echo "  cd $$i; $(MAKE) $(MFLAGS) clean"; \
 			( cd $$i; $(MAKE) $(MFLAGS) clean ); \
@@ -303,7 +312,7 @@ clean-local-srv: FORCE
 	rm -f *.tmp all-cffiles
 
 veryclean-local-srv: FORCE
-	@for i in back-* shell-backends tools; do \
+	@for i in back-* shell-backends slapi tools; do \
 		if test -d $$i -a -f $$i/Makefile ; then \
 			echo; echo "  cd $$i; $(MAKE) $(MFLAGS) clean"; \
 			( cd $$i; $(MAKE) $(MFLAGS) veryclean ); \
@@ -317,7 +326,7 @@ install-slapd: FORCE
 	-$(MKDIR) $(DESTDIR)$(localstatedir)
 	$(LTINSTALL) $(INSTALLFLAGS) -s -m 755 \
 		slapd$(EXEEXT) $(DESTDIR)$(libexecdir)
-	@for i in back-* shell-backends tools; do \
+	@for i in back-* shell-backends slapi tools; do \
 	    if test -d $$i -a -f $$i/Makefile ; then \
 		echo; echo "  cd $$i; $(MAKE) $(MFLAGS) install"; \
 		( cd $$i; $(MAKE) $(MFLAGS) install ); \
diff --git a/servers/slapd/add.c b/servers/slapd/add.c
index 85e6f7ca50..35a686f093 100644
--- a/servers/slapd/add.c
+++ b/servers/slapd/add.c
@@ -16,6 +16,7 @@
  */
 
 #include "portable.h"
+#include "slapi_common.h"
 
 #include <stdio.h>
 #include <ac/string.h>
@@ -24,13 +25,7 @@
 
 #include "ldap_pvt.h"
 #include "slap.h"
-
-static int slap_mods2entry(
-	Modifications *mods,
-	Entry **e,
-	int repl_user,
-	const char **text,
-	char *textbuf, size_t textlen );
+#include "slapi.h"
 
 int
 do_add( Connection *conn, Operation *op )
@@ -49,6 +44,8 @@ do_add( Connection *conn, Operation *op )
 	int			rc = LDAP_SUCCESS;
 	int	manageDSAit;
 
+	Slapi_PBlock *pb = op->o_pb;
+
 #ifdef NEW_LOGGING
 	LDAP_LOG( OPERATION, ENTRY, "do_add: conn %d enter\n", conn->c_connid,0,0 );
 #else
@@ -228,6 +225,31 @@ do_add( Connection *conn, Operation *op )
 		goto done;
 	}
 
+#if defined( LDAP_SLAPI )
+	slapi_pblock_set( pb, SLAPI_BACKEND, (void *)be );
+	slapi_pblock_set( pb, SLAPI_CONNECTION, (void *)conn );
+	slapi_pblock_set( pb, SLAPI_OPERATION, (void *)op );
+	slapi_pblock_set( pb, SLAPI_ADD_ENTRY, (void *)e );
+	slapi_pblock_set( pb, SLAPI_ADD_TARGET, (void *)dn.bv_val );
+	slapi_pblock_set( pb, SLAPI_MANAGEDSAIT, (void *)(1) );
+	slapi_pblock_set( pb, SLAPI_REQCONTROLS, (void *)op->o_ctrls );
+
+	rc = doPluginFNs( be, SLAPI_PLUGIN_PRE_ADD_FN, pb );
+	if ( rc != 0 && rc != LDAP_OTHER ) {
+		/*
+		 * either there is no preOp (add) plugins
+		 * or a plugin failed. Just log it
+		 * 
+		 * FIXME: is this correct?
+		 */
+#ifdef NEW_LOGGING
+		LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_add: add preOps failed\n"));
+#else
+		Debug (LDAP_DEBUG_TRACE, " add preOps failed.\n", 0, 0, 0);
+#endif
+	}
+#endif /* defined( LDAP_SLAPI ) */
+
 	/*
 	 * do the add if 1 && (2 || 3)
 	 * 1) there is an add function implemented in this backend;
@@ -314,6 +336,23 @@ do_add( Connection *conn, Operation *op )
 			      NULL, "operation not supported within namingContext", NULL, NULL );
 	}
 
+#if defined( LDAP_SLAPI )
+	rc = doPluginFNs( be, SLAPI_PLUGIN_POST_ADD_FN, pb );
+	if ( rc != 0 && rc != LDAP_OTHER ) {
+		/*
+		 * either there is no postOp (Add) plugins
+		 * or a plugin failed. Just log it
+		 *
+		 * FIXME: is this correct?
+		 */
+#ifdef NEW_LOGGING
+		LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_add: Add postOps failed\n"));
+#else
+		Debug (LDAP_DEBUG_TRACE, " Add postOps failed.\n", 0, 0, 0);
+#endif
+	}
+#endif /* defined( LDAP_SLAPI ) */
+
 done:
 	if( modlist != NULL ) {
 		slap_mods_free( modlist );
@@ -325,7 +364,8 @@ done:
 	return rc;
 }
 
-static int slap_mods2entry(
+int
+slap_mods2entry(
 	Modifications *mods,
 	Entry **e,
 	int repl_user,
diff --git a/servers/slapd/backend.c b/servers/slapd/backend.c
index 124ec7c422..fb1272b4b7 100644
--- a/servers/slapd/backend.c
+++ b/servers/slapd/backend.c
@@ -7,6 +7,7 @@
 
 
 #include "portable.h"
+#include "slapi_common.h"
 
 #include <stdio.h>
 
@@ -16,6 +17,7 @@
 #include <sys/stat.h>
 
 #include "slap.h"
+#include "slapi.h"
 #include "lutil.h"
 #include "lber_pvt.h"
 
@@ -686,12 +688,56 @@ backend_unbind(
 	Operation    *op
 )
 {
-	int	i;
+	int		i;
+	int     rc;
+	Slapi_PBlock *pb = op->o_pb;
+
+#if defined( LDAP_SLAPI )
+	slapi_pblock_set( pb, SLAPI_CONNECTION, (void *)conn );
+	slapi_pblock_set( pb, SLAPI_OPERATION, (void *)op );
+#endif /* defined( LDAP_SLAPI ) */
 
 	for ( i = 0; i < nbackends; i++ ) {
+#if defined( LDAP_SLAPI )
+		slapi_pblock_set( pb, SLAPI_BACKEND, (void *)&backends[i] );
+		rc = doPluginFNs( &backends[i], SLAPI_PLUGIN_PRE_UNBIND_FN,
+				(Slapi_PBlock *)pb );
+		if ( rc != 0 && rc != LDAP_OTHER ) {
+			/*
+			 * either there is no preOp (unbind) plugins
+			 * or a plugin failed. Just log it.
+			 *
+			 * FIXME: is this correct?
+			 */
+#ifdef NEW_LOGGING
+			LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_bind: Unbind preOps failed\n"));
+#else
+			Debug (LDAP_DEBUG_TRACE, " Unbind preOps failed.\n", 0, 0, 0);
+#endif
+		}
+#endif /* defined( LDAP_SLAPI ) */
+
 		if ( backends[i].be_unbind ) {
 			(*backends[i].be_unbind)( &backends[i], conn, op );
 		}
+
+#if defined( LDAP_SLAPI )
+		rc = doPluginFNs( &backends[i], SLAPI_PLUGIN_POST_UNBIND_FN,
+				(Slapi_PBlock *)pb );
+		if ( rc != 0 && rc != LDAP_OTHER ) {
+			/*
+			 * either there is no postOp (unbind) plugins
+			 * or a plugin failed. Just log it.
+			 *
+			 * FIXME: is this correct?
+			 */
+#ifdef NEW_LOGGING
+			LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_unbind: Unbind postOps failed\n"));
+#else
+			Debug (LDAP_DEBUG_TRACE, " Unbind postOps failed.\n", 0, 0, 0);
+#endif
+		}
+#endif /* defined( LDAP_SLAPI ) */
 	}
 
 	return 0;
diff --git a/servers/slapd/bind.c b/servers/slapd/bind.c
index 1b3220c2c3..f5062ba5cf 100644
--- a/servers/slapd/bind.c
+++ b/servers/slapd/bind.c
@@ -18,6 +18,7 @@
  */
 
 #include "portable.h"
+#include "slapi_common.h"
 
 #include <stdio.h>
 
@@ -26,6 +27,7 @@
 
 #include "ldap_pvt.h"
 #include "slap.h"
+#include "slapi.h"
 
 int
 do_bind(
@@ -47,6 +49,8 @@ do_bind(
 	struct berval cred = { 0, NULL };
 	Backend *be = NULL;
 
+	Slapi_PBlock *pb = op->o_pb;
+
 #ifdef NEW_LOGGING
 	LDAP_LOG( OPERATION, ENTRY, "do_bind: conn %d\n", conn->c_connid, 0, 0 );
 #else
@@ -526,6 +530,30 @@ do_bind(
 		goto cleanup;
 	}
 
+#if defined( LDAP_SLAPI )
+	slapi_pblock_set( pb, SLAPI_BACKEND, (void *)be );
+	slapi_pblock_set( pb, SLAPI_CONNECTION, (void *)conn );
+	slapi_pblock_set( pb, SLAPI_OPERATION, (void *)op );
+	slapi_pblock_set( pb, SLAPI_BIND_TARGET, (void *)dn.bv_val );
+	slapi_pblock_set( pb, SLAPI_BIND_METHOD, (void *)method );
+	slapi_pblock_set( pb, SLAPI_MANAGEDSAIT, (void *)(1) );
+
+	rc = doPluginFNs( be, SLAPI_PLUGIN_PRE_BIND_FN, pb );
+	if ( rc != 0 && rc != LDAP_OTHER ) {
+		/*
+		 * either there is no preOp (bind) plugins
+		 * or a plugin failed. Just log it
+		 *
+		 * FIXME: is this correct?
+		 */
+#ifdef NEW_LOGGING
+		LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_bind: Bind preOps  failed\n"));
+#else
+		Debug(LDAP_DEBUG_TRACE, " Bind preOps failed.\n", 0, 0, 0);
+#endif
+	}
+#endif /* defined( LDAP_SLAPI ) */
+
 	if ( be->be_bind ) {
 		int ret;
 
@@ -592,6 +620,23 @@ do_bind(
 			NULL, NULL );
 	}
 
+#if defined( LDAP_SLAPI )
+	rc = doPluginFNs( be, SLAPI_PLUGIN_POST_BIND_FN, pb );
+	if ( rc != 0 && rc != LDAP_OTHER ) {
+		/*
+		 * either there is no pretOp (bind) plugins
+		 * or a plugin failed. Just log it
+		 *
+		 * FIXME: is this correct?
+		 */
+#ifdef NEW_LOGGING
+		LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_bind: Bind postOps failed\n"));
+#else
+		Debug (LDAP_DEBUG_TRACE, " Bind postOps failed.\n", 0, 0, 0);
+#endif
+	}
+#endif /* defined( LDAP_SLAPI ) */
+
 cleanup:
 	conn->c_sasl_bindop = NULL;
 
diff --git a/servers/slapd/compare.c b/servers/slapd/compare.c
index 81e3e9f54e..ab0546ffc9 100644
--- a/servers/slapd/compare.c
+++ b/servers/slapd/compare.c
@@ -16,12 +16,14 @@
  */
 
 #include "portable.h"
+#include "slapi_common.h"
 
 #include <stdio.h>
 #include <ac/socket.h>
 
 #include "ldap_pvt.h"
 #include "slap.h"
+#include "slapi.h"
 
 static int compare_entry(
 	Connection *conn,
@@ -48,6 +50,8 @@ do_compare(
 	const char *text = NULL;
 	int manageDSAit;
 
+	Slapi_PBlock *pb = op->o_pb;
+
 	ava.aa_desc = NULL;
 
 #ifdef NEW_LOGGING
@@ -267,6 +271,32 @@ do_compare(
 	/* deref suffix alias if appropriate */
 	suffix_alias( be, &ndn );
 
+#if defined( LDAP_SLAPI )
+	slapi_pblock_set( pb, SLAPI_BACKEND, (void *)be );
+	slapi_pblock_set( pb, SLAPI_CONNECTION, (void *)conn );
+	slapi_pblock_set( pb, SLAPI_OPERATION, (void *)op );
+	slapi_pblock_set( pb, SLAPI_BIND_TARGET, (void *)dn.bv_val );
+	slapi_pblock_set( pb, SLAPI_MANAGEDSAIT, (void *)(1) );
+	slapi_pblock_set( pb, SLAPI_REQCONTROLS, (void *)op->o_ctrls );
+	slapi_pblock_set( pb, SLAPI_COMPARE_TYPE, (void *)desc.bv_val );
+	slapi_pblock_set( pb, SLAPI_COMPARE_VALUE, (void *)&value );
+
+	rc = doPluginFNs( be, SLAPI_PLUGIN_PRE_COMPARE_FN, pb );
+	if ( rc != 0 && rc != LDAP_OTHER ) {
+		/*
+		 * either there is no preOp (compare) plugins
+		 * or a plugin failed. Just log it
+		 *
+		 * FIXME: is this correct?
+		 */
+#ifdef NEW_LOGGING
+		LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_compare: compare preOps failed\n"));
+#else
+		Debug (LDAP_DEBUG_TRACE, " compare preOps failed.\n", 0, 0, 0);
+#endif
+	}
+#endif /* defined( LDAP_SLAPI ) */
+
 	if ( be->be_compare ) {
 		(*be->be_compare)( be, conn, op, &pdn, &ndn, &ava );
 	} else {
@@ -275,6 +305,23 @@ do_compare(
 			NULL, NULL );
 	}
 
+#if defined( LDAP_SLAPI )
+	rc = doPluginFNs( be, SLAPI_PLUGIN_POST_COMPARE_FN, pb );
+	if ( rc != 0 && rc != LDAP_OTHER ) {
+		/*
+		 * either there is no postOp (compare) plugins
+		 * or a plugin failed. Just log it
+		 *
+		 * FIXME: is this correct?
+		 */
+#ifdef NEW_LOGGING
+		LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_compare: compare postOps failed\n"));
+#else
+		Debug (LDAP_DEBUG_TRACE, " compare postOps failed.\n", 0, 0, 0);
+#endif
+	}
+#endif /* defined( LDAP_SLAPI ) */
+
 cleanup:
 	free( pdn.bv_val );
 	free( ndn.bv_val );
diff --git a/servers/slapd/config.c b/servers/slapd/config.c
index 45616ae406..d87bf6f432 100644
--- a/servers/slapd/config.c
+++ b/servers/slapd/config.c
@@ -6,6 +6,7 @@
  */
 
 #include "portable.h"
+#include "slapi_common.h"
 
 #include <stdio.h>
 
@@ -18,6 +19,7 @@
 #include "lutil.h"
 #include "ldap_pvt.h"
 #include "slap.h"
+#include "slapi.h"
 
 #define ARGS_STEP	512
 
@@ -2311,6 +2313,49 @@ read_config( const char *fname, int depth )
 #endif
 #endif /* !SLAPD_RLOOKUPS */
 
+		/* Netscape plugins */
+		} else if ( strcasecmp( cargv[0], "plugin" ) == 0 ) {
+#if defined( LDAP_SLAPI )
+
+			/*
+			 * a "plugin" line must be inside a database
+			 * definition, since we implement pre-,post- 
+			 * and extended operation plugins
+			 */
+			if ( be == NULL ) {
+#ifdef NEW_LOGGING
+				LDAP_LOG( CONFIG, INFO, 
+					"%s: line %d: plugin line must appear "
+					"inside a database definition.\n",
+					fname, lineno, 0 );
+#else
+				Debug( LDAP_DEBUG_ANY, "%s: line %d: plugin "
+				    "line must appear inside a database "
+				    "definition\n", fname, lineno, 0 );
+#endif
+				return( 1 );
+			}
+
+			if ( netscape_plugin( be, fname, lineno, cargc, cargv ) 
+					!= LDAP_SUCCESS ) {
+				return( 1 );
+			}
+
+#else /* !defined( LDAP_SLAPI ) */
+#ifdef NEW_LOGGING
+			LDAP_LOG( CONFIG, INFO, 
+				"%s: line %d: SLAPI not supported.\n",
+				fname, lineno, 0 );
+#else
+			Debug( LDAP_DEBUG_ANY, "%s: line %d: SLAPI "
+			    "not supported.\n", fname, lineno, 0 );
+#endif
+			return( 1 );
+			
+#endif /* !defined( LDAP_SLAPI ) */
+
+
+
 		/* pass anything else to the current backend info/db config routine */
 		} else {
 			if ( bi != NULL ) {
diff --git a/servers/slapd/connection.c b/servers/slapd/connection.c
index aeed4237b8..8dbf0e63d7 100644
--- a/servers/slapd/connection.c
+++ b/servers/slapd/connection.c
@@ -395,22 +395,28 @@ long connection_init(
 	if( c == NULL ) {
 #ifdef NEW_LOGGING
 		LDAP_LOG( CONNECTION, INFO, 
-			   "connection_init: skt %d	 connection table full (%d/%d)\n",
-			   s, i, dtblsize );
+			   "connection_init: skt %d connection table full "
+			   "(%d/%d)\n", s, i, dtblsize );
 #else
 		Debug( LDAP_DEBUG_ANY,
-				"connection_init(%d): connection table full (%d/%d)\n",
-				s, i, dtblsize);
+				"connection_init(%d): connection table full "
+				"(%d/%d)\n", s, i, dtblsize);
 #endif
 	    ldap_pvt_thread_mutex_unlock( &connections_mutex );
 	    return -1;
 	}
-    }
+    	}
 #endif
 
-    assert( c != NULL );
+	assert( c != NULL );
 
 	if( c->c_struct_state == SLAP_C_UNINITIALIZED ) {
+		c->c_send_ldap_result = slap_send_ldap_result;
+		c->c_send_search_entry = slap_send_search_entry;
+		c->c_send_search_result = slap_send_search_result;
+		c->c_send_search_reference = slap_send_search_reference;
+		c->c_send_ldap_extended = slap_send_ldap_extended;
+
 		c->c_authmech.bv_val = NULL;
 		c->c_authmech.bv_len = 0;
 		c->c_dn.bv_val = NULL;
diff --git a/servers/slapd/controls.c b/servers/slapd/controls.c
index cf8fdd2469..465884c412 100644
--- a/servers/slapd/controls.c
+++ b/servers/slapd/controls.c
@@ -106,6 +106,12 @@ get_supported_ctrl(int index)
 	return supportedControls[index].sc_oid;
 }
 
+slap_mask_t
+get_supported_ctrl_mask(int index)
+{
+	return supportedControls[index].sc_mask;
+}
+
 static struct slap_control *
 find_ctrl( const char *oid )
 {
diff --git a/servers/slapd/delete.c b/servers/slapd/delete.c
index 97f073e1b9..849a494bc7 100644
--- a/servers/slapd/delete.c
+++ b/servers/slapd/delete.c
@@ -16,6 +16,7 @@
  */
 
 #include "portable.h"
+#include "slapi_common.h"
 
 #include <stdio.h>
 
@@ -24,6 +25,7 @@
 
 #include "ldap_pvt.h"
 #include "slap.h"
+#include "slapi.h"
 
 int
 do_delete(
@@ -39,6 +41,8 @@ do_delete(
 	int rc;
 	int manageDSAit;
 
+	Slapi_PBlock *pb = op->o_pb;
+
 #ifdef NEW_LOGGING
 	LDAP_LOG( OPERATION, ENTRY, 
 		"do_delete: conn %d\n", conn->c_connid, 0, 0 );
@@ -153,6 +157,30 @@ do_delete(
 	/* deref suffix alias if appropriate */
 	suffix_alias( be, &ndn );
 
+#if defined( LDAP_SLAPI )
+	slapi_pblock_set( pb, SLAPI_BACKEND, (void *)be );
+	slapi_pblock_set( pb, SLAPI_CONNECTION, (void *)conn );
+	slapi_pblock_set( pb, SLAPI_OPERATION, (void *)op );
+	slapi_pblock_set( pb, SLAPI_BIND_TARGET, (void *)dn.bv_val );
+	slapi_pblock_set( pb, SLAPI_MANAGEDSAIT, (void *)(1) );
+	slapi_pblock_set( pb, SLAPI_REQCONTROLS, (void *)op->o_ctrls );
+
+	rc = doPluginFNs( be, SLAPI_PLUGIN_PRE_DELETE_FN, pb );
+	if ( rc != 0 && rc != LDAP_OTHER ) {
+		/*
+		 * either there is no preOp (delete) plugins
+		 * or a plugin failed. Just log it
+		 *
+		 * FIXME: is this correct?
+		 */
+#ifdef NEW_LOGGING
+		LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_delete: delete preOps failed\n"));
+#else
+		Debug (LDAP_DEBUG_TRACE, " delete preOps failed.\n", 0, 0, 0);
+#endif
+	}
+#endif /* defined( LDAP_SLAPI ) */
+
 	/*
 	 * do the delete if 1 && (2 || 3)
 	 * 1) there is a delete function implemented in this backend;
@@ -193,6 +221,23 @@ do_delete(
 			NULL, "operation not supported within namingContext", NULL, NULL );
 	}
 
+#if defined( LDAP_SLAPI )
+	rc = doPluginFNs( be, SLAPI_PLUGIN_POST_DELETE_FN, pb );
+	if ( rc != 0 && rc != LDAP_OTHER ) {
+		/*
+		 * either there is no postOp (delete) plugins
+		 * or a plugin failed. Just log it
+		 *
+		 * FIXME: is this correct?
+		 */
+#ifdef NEW_LOGGING
+		LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_delete: delete postOps failed\n"));
+#else
+		Debug (LDAP_DEBUG_TRACE, " delete postOps failed.\n", 0, 0, 0);
+#endif
+	}
+#endif /* defined( LDAP_SLAPI ) */
+
 cleanup:
 	free( pdn.bv_val );
 	free( ndn.bv_val );
diff --git a/servers/slapd/extended.c b/servers/slapd/extended.c
index dfff66d4d7..84d8698d5a 100644
--- a/servers/slapd/extended.c
+++ b/servers/slapd/extended.c
@@ -26,14 +26,18 @@
  */
 
 #include "portable.h"
+#include "slapi_common.h"
 
 #include <stdio.h>
 #include <ac/socket.h>
 #include <ac/string.h>
 
 #include "slap.h"
+#include "slapi.h"
 #include "lber_pvt.h"
 
+#define UNSUPPORTED_EXTENDEDOP "unsupported extended operation"
+
 static struct extop_list {
 	struct extop_list *next;
 	struct berval oid;
@@ -102,6 +106,12 @@ do_extended(
 	struct berval *rspdata;
 	LDAPControl **rspctrls;
 
+	Slapi_PBlock    *pb = op->o_pb;
+	SLAPI_FUNC      funcAddr = NULL;
+	int             extop_rc;
+	int             msg_sent=FALSE;
+	char            *result_msg="";
+
 #ifdef NEW_LOGGING
 	LDAP_LOG( OPERATION, ENTRY, "do_extended: conn %d\n", conn->c_connid, 0, 0 );
 #else
@@ -136,7 +146,10 @@ do_extended(
 		goto done;
 	}
 
-	if( !(ext = find_extop(supp_ext_list, &reqoid)) ) {
+	/* Netscape extended operation */
+	getPluginFunc( &reqoid, &funcAddr );
+
+	if( !(ext = find_extop(supp_ext_list, &reqoid)) && !(funcAddr) ) {
 #ifdef NEW_LOGGING
 		LDAP_LOG( OPERATION, ERR, 
 			"do_extended: conn %d  unsupported operation \"%s\"\n",
@@ -202,29 +215,72 @@ do_extended(
 	text = NULL;
 	refs = NULL;
 
-	rc = (ext->ext_main)( conn, op,
-		reqoid.bv_val, reqdata.bv_val ? &reqdata : NULL,
-		&rspoid, &rspdata, &rspctrls, &text, &refs );
+	if (ext != NULL) { /* OpenLDAP extended operation */
+		rc = (ext->ext_main)( conn, op,
+			  reqoid.bv_val, reqdata.bv_val ? &reqdata : NULL,
+			  &rspoid, &rspdata, &rspctrls, &text, &refs );
+
+		if( rc != SLAPD_ABANDON ) {
+			if ( rc == LDAP_REFERRAL && refs == NULL ) {
+				refs = referral_rewrite( default_referral,
+					NULL, NULL, LDAP_SCOPE_DEFAULT );
+			}
 
-	if( rc != SLAPD_ABANDON ) {
-		if ( rc == LDAP_REFERRAL && refs == NULL ) {
-			refs = referral_rewrite( default_referral,
-				NULL, NULL, LDAP_SCOPE_DEFAULT );
+			send_ldap_extended( conn, op, rc, NULL, text, refs,
+				rspoid, rspdata, rspctrls );
+
+			ber_bvarray_free( refs );
 		}
 
-		send_ldap_extended( conn, op, rc, NULL, text, refs,
-			rspoid, rspdata, rspctrls );
+		if ( rspoid != NULL ) {
+			free( rspoid );
+		}
 
-		ber_bvarray_free( refs );
+		if ( rspdata != NULL ) {
+			ber_bvfree( rspdata );
+		}
+#if !defined( LDAP_SLAPI )
 	}
+#else /* defined( LDAP_SLAPI ) */
+		goto done;  /* end of OpenLDAP extended operation */
+
+	} else { /* start of Netscape extended operation */
+		if ( ( rc = slapi_pblock_set( pb, SLAPI_EXT_OP_REQ_OID,(void *)reqoid.bv_val) ) == 0 &&
+				( rc = slapi_pblock_set( pb, SLAPI_EXT_OP_REQ_VALUE,(void *)&reqdata) ) == 0 &&
+				( rc = slapi_pblock_set( pb, SLAPI_CONNECTION,(void *)conn) ) == 0  &&
+				( rc = slapi_pblock_set( pb, SLAPI_OPERATION, (void *)op) ) == 0) {
+			extop_rc = (*funcAddr)( pb );
+			if ( extop_rc == SLAPI_PLUGIN_EXTENDED_SENT_RESULT ) {
+				msg_sent = TRUE;
+			} else if ( extop_rc == SLAPI_PLUGIN_EXTENDED_NOT_HANDLED ) {
+				rc = LDAP_PROTOCOL_ERROR;
+				result_msg = UNSUPPORTED_EXTENDEDOP;
+			} else {
+				if ( ( rc = slapi_pblock_get(pb, SLAPI_EXT_OP_RET_OID,&rspoid) ) == 0 &&
+						  ( rc = slapi_pblock_get(pb, SLAPI_EXT_OP_RET_VALUE,&rspdata) ) == 0 ) {
+					send_ldap_extended( conn, op, extop_rc, NULL, text, refs,
+                                                        rspoid, rspdata, rspctrls );
+					msg_sent = TRUE;
+				} else {
+					rc = LDAP_OPERATIONS_ERROR;
+				}
+			}
+		} else {
+			rc = LDAP_OPERATIONS_ERROR;
+		}
 
-	if ( rspoid != NULL ) {
-		free( rspoid );
-	}
+		if ( rc != LDAP_SUCCESS && msg_sent == FALSE ) {
+			send_ldap_result( conn, op, rc, NULL, result_msg, NULL, NULL );
+		}
+		if ( rspoid != NULL ) {
+			free( rspoid );
+		}
+		if ( rspdata != NULL ) {
+			ber_bvfree( rspdata );
+		}
 
-	if ( rspdata != NULL ) {
-		ber_bvfree( rspdata );
-	}
+	} /* end of Netscape extended operation */
+#endif /* defined( LDAP_SLAPI ) */
 
 done:
 	return rc;
diff --git a/servers/slapd/main.c b/servers/slapd/main.c
index 1dc199c838..40a036ce89 100644
--- a/servers/slapd/main.c
+++ b/servers/slapd/main.c
@@ -4,6 +4,7 @@
  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
  */
 #include "portable.h"
+#include "slapi_common.h"
 
 #include <stdio.h>
 
@@ -16,7 +17,9 @@
 
 #include "ldap_pvt.h"
 
+
 #include "slap.h"
+#include "slapi.h"
 #include "lutil.h"
 #include "ldif.h"
 
@@ -405,6 +408,20 @@ int main( int argc, char **argv )
 	(void) ldap_pvt_tls_set_option( NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &rc );
 #endif
 
+#ifdef LDAP_SLAPI
+	if ( slapi_init() != 0 ) {
+#ifdef NEW_LOGGING
+		LDAP_LOG( OPERATION, CRIT, "main: slapi initialization error\n", 0, 0, 0 );
+#else
+		Debug( LDAP_DEBUG_ANY,
+		    "slapi initialization error\n",
+		    0, 0, 0 );
+#endif
+
+		goto destroy;
+	}
+#endif /* LDAP_SLAPI */
+
 	if ( read_config( configfile, 0 ) != 0 ) {
 		rc = 1;
 		SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 19 );
diff --git a/servers/slapd/modify.c b/servers/slapd/modify.c
index 0f0c716375..e9c7bd72b7 100644
--- a/servers/slapd/modify.c
+++ b/servers/slapd/modify.c
@@ -16,6 +16,7 @@
  */
 
 #include "portable.h"
+#include "slapi_common.h"
 
 #include <stdio.h>
 
@@ -27,6 +28,7 @@
 
 #include "ldap_pvt.h"
 #include "slap.h"
+#include "slapi.h"
 
 int
 do_modify(
@@ -49,6 +51,8 @@ do_modify(
 	const char	*text;
 	int manageDSAit;
 
+	Slapi_PBlock *pb = op->o_pb;
+
 #ifdef NEW_LOGGING
 	LDAP_LOG( OPERATION, ENTRY, "do_modify: enter\n", 0, 0, 0 );
 #else
@@ -303,6 +307,30 @@ do_modify(
 	/* deref suffix alias if appropriate */
 	suffix_alias( be, &ndn );
 
+#if defined( LDAP_SLAPI )
+	slapi_pblock_set( pb, SLAPI_BACKEND, (void *)be );
+	slapi_pblock_set( pb, SLAPI_CONNECTION, (void *)conn );
+	slapi_pblock_set( pb, SLAPI_OPERATION, (void *)op );
+	slapi_pblock_set( pb, SLAPI_BIND_TARGET, (void *)dn.bv_val );
+	slapi_pblock_set( pb, SLAPI_REQCONTROLS, (void *)op->o_ctrls );
+	slapi_pblock_set( pb, SLAPI_MANAGEDSAIT, (void *)(1) );
+
+	rc = doPluginFNs( be, SLAPI_PLUGIN_PRE_MODIFY_FN, pb );
+	if ( rc != 0 && rc != LDAP_OTHER ) {
+		/*
+		 * either there is no preOp (modify) plugins
+		 * or a plugin failed. Just log it
+		 *
+		 * FIXME: is this correct?
+		 */
+#ifdef NEW_LOGGING
+		LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_modify: modify preOps failed\n"));
+#else
+		Debug (LDAP_DEBUG_TRACE, " modify preOps failed.\n", 0, 0, 0);
+#endif
+	}
+#endif /* defined( LDAP_SLAPI ) */
+
 	/*
 	 * do the modify if 1 && (2 || 3)
 	 * 1) there is a modify function implemented in this backend;
@@ -380,6 +408,23 @@ do_modify(
 			NULL, NULL );
 	}
 
+#if defined( LDAP_SLAPI )
+	rc = doPluginFNs( be, SLAPI_PLUGIN_POST_MODIFY_FN, pb );
+	if ( rc != 0 && rc != LDAP_OTHER ) {
+		/*
+		 * either there is no postOp (modify) plugins
+		 * or a plugin failed. Just log it
+		 *
+		 * FIXME: is this correct?
+		 */
+#ifdef NEW_LOGGING
+		LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_modify: modify postOps failed\n"));
+#else
+		Debug (LDAP_DEBUG_TRACE, " modify postOps failed.\n", 0, 0, 0);
+#endif
+	}
+#endif /* defined( LDAP_SLAPI ) */
+
 cleanup:
 	free( pdn.bv_val );
 	free( ndn.bv_val );
diff --git a/servers/slapd/modrdn.c b/servers/slapd/modrdn.c
index 372f0a33e8..a4dc801038 100644
--- a/servers/slapd/modrdn.c
+++ b/servers/slapd/modrdn.c
@@ -29,6 +29,7 @@
  */
 
 #include "portable.h"
+#include "slapi_common.h"
 
 #include <stdio.h>
 
@@ -37,6 +38,7 @@
 
 #include "ldap_pvt.h"
 #include "slap.h"
+#include "slapi.h"
 
 int
 do_modrdn(
@@ -64,6 +66,8 @@ do_modrdn(
 	const char *text;
 	int manageDSAit;
 
+	Slapi_PBlock *pb = op->o_pb;
+
 #ifdef NEW_LOGGING
 	LDAP_LOG( OPERATION, ENTRY, "do_modrdn: begin\n", 0, 0, 0 );
 #else
@@ -324,6 +328,34 @@ do_modrdn(
 	/* deref suffix alias if appropriate */
 	suffix_alias( be, &ndn );
 
+#if defined( LDAP_SLAPI )
+	slapi_pblock_set( pb, SLAPI_BACKEND, (void *)be );
+	slapi_pblock_set( pb, SLAPI_CONNECTION, (void *)conn );
+	slapi_pblock_set( pb, SLAPI_OPERATION, (void *)op );
+	slapi_pblock_set( pb, SLAPI_BIND_TARGET, (void *)dn.bv_val );
+	slapi_pblock_set( pb, SLAPI_MODRDN_NEWRDN, (void *)newrdn.bv_val );
+	slapi_pblock_set( pb, SLAPI_MODRDN_NEWSUPERIOR,
+			(void *)newSuperior.bv_val );
+	slapi_pblock_set( pb, SLAPI_MODRDN_DELOLDRDN, (void *)deloldrdn );
+	slapi_pblock_set( pb, SLAPI_REQCONTROLS, (void *)op->o_ctrls );
+	slapi_pblock_set( pb, SLAPI_MANAGEDSAIT, (void *)(1) );
+
+	rc = doPluginFNs( be, SLAPI_PLUGIN_PRE_MODRDN_FN, pb );
+	if ( rc != 0 && rc != LDAP_OTHER ) {
+		/*
+		 * either there is no preOp (modrdn) plugins
+		 * or a plugin failed. Just log it
+		 *
+		 * FIXME: is this correct?
+		 */
+#ifdef NEW_LOGGING
+		LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_modrdn: modrdn preOps failed\n"));
+#else
+		Debug (LDAP_DEBUG_TRACE, " modrdn preOps failed.\n", 0, 0, 0);
+#endif
+	}
+#endif /* defined( LDAP_SLAPI ) */
+
 	/*
 	 * do the add if 1 && (2 || 3)
 	 * 1) there is an add function implemented in this backend;
@@ -370,6 +402,23 @@ do_modrdn(
 			NULL, NULL );
 	}
 
+#if defined( LDAP_SLAPI )
+	rc = doPluginFNs( be, SLAPI_PLUGIN_POST_MODRDN_FN, pb );
+	if ( rc != 0 && rc != LDAP_OTHER ) {
+		/*
+		 * either there is no postOp (modrdn) plugins
+		 * or a plugin failed. Just log it
+		 *
+		 * FIXME: is this correct?
+		 */
+#ifdef NEW_LOGGING
+		LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_modrdn: modrdn postOps failed\n"));
+#else
+		Debug (LDAP_DEBUG_TRACE, " modrdn postOps failed.\n", 0, 0, 0);
+#endif
+	}
+#endif /* defined( LDAP_SLAPI ) */
+
 cleanup:
 	free( pdn.bv_val );
 	free( ndn.bv_val );
diff --git a/servers/slapd/operation.c b/servers/slapd/operation.c
index 59fc1b9cd7..4745076706 100644
--- a/servers/slapd/operation.c
+++ b/servers/slapd/operation.c
@@ -6,6 +6,7 @@
  */
 
 #include "portable.h"
+#include "slapi_common.h"
 
 #include <stdio.h>
 
@@ -13,6 +14,7 @@
 #include <ac/socket.h>
 
 #include "slap.h"
+#include "slapi.h"
 
 
 void
@@ -42,6 +44,12 @@ slap_op_free( Operation *op )
 	}
 #endif /* LDAP_CLIENT_UPDATE */
 
+#if defined( LDAP_SLAPI )
+	if ( op->o_pb != NULL ) {
+		slapi_pblock_destroy( (Slapi_PBlock *)op->o_pb );
+	}
+#endif /* defined( LDAP_SLAPI ) */
+
 	free( (char *) op );
 }
 
@@ -64,5 +72,9 @@ slap_op_alloc(
 	op->o_time = slap_get_time();
 	op->o_opid = id;
 
+#if defined( LDAP_SLAPI )
+	op->o_pb = slapi_pblock_new();
+#endif /* defined( LDAP_SLAPI ) */
+
 	return( op );
 }
diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h
index 0085f5f8d6..f00570c60d 100644
--- a/servers/slapd/proto-slap.h
+++ b/servers/slapd/proto-slap.h
@@ -84,7 +84,13 @@ LDAP_SLAPD_F (AttributeDescription *) ad_find_lang LDAP_P((
 
 LDAP_SLAPD_F (AttributeName *) str2anlist LDAP_P(( AttributeName *an,
 	char *str, const char *brkstr ));
-LDAP_SLAPD_F (int) an_find LDAP_P(( AttributeName *a, struct berval *s ));	
+LDAP_SLAPD_F (int) an_find LDAP_P(( AttributeName *a, struct berval *s ));
+
+/*
+ * add.c
+ */
+LDAP_SLAPD_F (int) slap_mods2entry LDAP_P(( Modifications *mods, Entry **e,
+	int repl_user, const char **text, char *textbuf, size_t textlen ));
 
 /*
  * at.c
@@ -271,6 +277,8 @@ LDAP_SLAPD_F (int) get_ctrls LDAP_P((
 
 LDAP_SLAPD_F (char *) get_supported_ctrl LDAP_P((int index));
 
+LDAP_SLAPD_F (slap_mask_t) get_supported_ctrl_mask LDAP_P((int index));
+
 /*
  * config.c
  */
@@ -773,7 +781,7 @@ LDAP_SLAPD_F (void) replog LDAP_P(( Backend *be, Operation *op,
 /*
  * result.c
  */
-LDAP_SLAPD_F (void) send_ldap_result LDAP_P((
+LDAP_SLAPD_F (void) slap_send_ldap_result LDAP_P((
 	Connection *conn, Operation *op,
 	ber_int_t err, const char *matched, const char *text,
 	BerVarray refs,
@@ -791,7 +799,7 @@ LDAP_SLAPD_F (void) send_ldap_disconnect LDAP_P((
 	Connection *conn, Operation *op,
 	ber_int_t err, const char *text ));
 
-LDAP_SLAPD_F (void) send_ldap_extended LDAP_P((
+LDAP_SLAPD_F (void) slap_send_ldap_extended LDAP_P((
 	Connection *conn, Operation *op,
 	ber_int_t err, const char *matched,
 	const char *text, BerVarray refs,
@@ -803,20 +811,20 @@ LDAP_SLAPD_F (void) send_ldap_partial LDAP_P((
 	const char *rspoid, struct berval *rspdata,
 	LDAPControl **ctrls ));
 
-LDAP_SLAPD_F (void) send_search_result LDAP_P((
+LDAP_SLAPD_F (void) slap_send_search_result LDAP_P((
 	Connection *conn, Operation *op,
 	ber_int_t err, const char *matched, const char *text,
 	BerVarray refs,
 	LDAPControl **ctrls,
 	int nentries ));
 
-LDAP_SLAPD_F (int) send_search_reference LDAP_P((
+LDAP_SLAPD_F (int) slap_send_search_reference LDAP_P((
 	Backend *be, Connection *conn, Operation *op,
 	Entry *e, BerVarray refs,
 	LDAPControl **ctrls,
 	BerVarray *v2refs ));
 
-LDAP_SLAPD_F (int) send_search_entry LDAP_P((
+LDAP_SLAPD_F (int) slap_send_search_entry LDAP_P((
 	Backend *be, Connection *conn, Operation *op,
 	Entry *e, AttributeName *attrs, int attrsonly,
 	LDAPControl **ctrls ));
diff --git a/servers/slapd/result.c b/servers/slapd/result.c
index 7f87db28d4..d26573bb3b 100644
--- a/servers/slapd/result.c
+++ b/servers/slapd/result.c
@@ -429,7 +429,7 @@ send_ldap_disconnect(
 }
 
 void
-send_ldap_result(
+slap_send_ldap_result(
     Connection	*conn,
     Operation	*op,
     ber_int_t	err,
@@ -545,7 +545,7 @@ send_ldap_sasl(
 }
 
 void
-send_ldap_extended(
+slap_send_ldap_extended(
     Connection	*conn,
     Operation	*op,
     ber_int_t	err,
@@ -583,7 +583,7 @@ send_ldap_extended(
 
 
 void
-send_search_result(
+slap_send_search_result(
     Connection	*conn,
     Operation	*op,
     ber_int_t	err,
@@ -661,7 +661,7 @@ send_search_result(
 }
 
 int
-send_search_entry(
+slap_send_search_entry(
     Backend	*be,
     Connection	*conn,
     Operation	*op,
@@ -1214,7 +1214,7 @@ error_return:;
 }
 
 int
-send_search_reference(
+slap_send_search_reference(
     Backend	*be,
     Connection	*conn,
     Operation	*op,
diff --git a/servers/slapd/root_dse.c b/servers/slapd/root_dse.c
index 312052605b..86777acfae 100644
--- a/servers/slapd/root_dse.c
+++ b/servers/slapd/root_dse.c
@@ -11,13 +11,18 @@
  */
 
 #include "portable.h"
+#include "slapi_common.h"
 
 #include <stdio.h>
 #include <ac/string.h>
 
 #include "slap.h"
+#include "slapi.h"
 #include <ldif.h>
 #include "lber_pvt.h"
+#include "slapi/slapi_utils.h"
+
+struct berval *ns_get_supported_extop (int);
 
 static struct berval supportedFeatures[] = {
 	BER_BVC(LDAP_FEATURE_ALL_OPERATIONAL_ATTRS), /* all Operational Attributes ("+") */
@@ -134,6 +139,14 @@ root_dse_info(
 			return LDAP_OTHER;
 	}
 
+#if defined( LDAP_SLAPI )
+	/* netscape supportedExtension */
+	for ( i = 0; (bv = ns_get_supported_extop(i)) != NULL; i++ ) {
+		vals[0] = *bv;
+		attr_merge( e, ad_supportedExtension, vals );
+	}
+#endif /* defined( LDAP_SLAPI ) */
+
 	/* supportedFeatures */
 	if( attr_merge( e, ad_supportedFeatures, supportedFeatures ) )
 		return LDAP_OTHER;
diff --git a/servers/slapd/search.c b/servers/slapd/search.c
index 4699633403..3260f8ab34 100644
--- a/servers/slapd/search.c
+++ b/servers/slapd/search.c
@@ -16,6 +16,7 @@
  */
 
 #include "portable.h"
+#include "slapi_common.h"
 
 #include <stdio.h>
 
@@ -24,6 +25,7 @@
 
 #include "ldap_pvt.h"
 #include "slap.h"
+#include "slapi.h"
 
 int
 do_search(
@@ -44,6 +46,8 @@ do_search(
 	const char	*text;
 	int			manageDSAit;
 
+	Slapi_PBlock *pb = op->o_pb;
+
 #ifdef NEW_LOGGING
 	LDAP_LOG( OPERATION, ENTRY, "do_search: conn %d\n", conn->c_connid, 0, 0 );
 #else
@@ -310,6 +314,37 @@ do_search(
 	/* deref the base if needed */
 	suffix_alias( be, &nbase );
 
+#if defined( LDAP_SLAPI )
+	slapi_pblock_set( pb, SLAPI_BACKEND, (void *)be );
+	slapi_pblock_set( pb, SLAPI_CONNECTION, (void *)conn );
+	slapi_pblock_set( pb, SLAPI_OPERATION, (void *)op );
+	slapi_pblock_set( pb, SLAPI_BIND_TARGET, (void *)base.bv_val );
+	slapi_pblock_set( pb, SLAPI_SEARCH_SCOPE, (void *)scope );
+	slapi_pblock_set( pb, SLAPI_SEARCH_DEREF, (void *)deref );
+	slapi_pblock_set( pb, SLAPI_SEARCH_SIZELIMIT, (void *)sizelimit );
+	slapi_pblock_set( pb, SLAPI_SEARCH_TIMELIMIT, (void *)timelimit );
+	slapi_pblock_set( pb, SLAPI_SEARCH_FILTER, (void *)filter );
+	slapi_pblock_set( pb, SLAPI_SEARCH_STRFILTER, (void *)fstr.bv_val );
+	slapi_pblock_set( pb, SLAPI_SEARCH_ATTRSONLY, (void *)attrsonly );
+	slapi_pblock_set( pb, SLAPI_REQCONTROLS, (void *)op->o_ctrls );
+	slapi_pblock_set( pb, SLAPI_MANAGEDSAIT, (void *)(1) );
+
+	rc = doPluginFNs( be, SLAPI_PLUGIN_PRE_SEARCH_FN, pb );
+	if ( rc != 0 && rc != LDAP_OTHER ) {
+		/*
+		 * either there is no preOp (search) plugins
+		 * or a plugin failed. Just log it
+		 *
+		 * FIXME: is this correct?
+		 */
+#ifdef NEW_LOGGING
+		LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_search: search preOps failed\n"));
+#else
+		Debug(LDAP_DEBUG_TRACE, "search preOps failed.\n", 0, 0, 0);
+#endif
+    }
+#endif /* defined( LDAP_SLAPI ) */
+
 	/* actually do the search and send the result(s) */
 	if ( be->be_search ) {
 		(*be->be_search)( be, conn, op, &pbase, &nbase,
@@ -321,6 +356,23 @@ do_search(
 			NULL, NULL );
 	}
 
+#if defined( LDAP_SLAPI )
+	rc = doPluginFNs( be, SLAPI_PLUGIN_POST_SEARCH_FN, pb );
+	if ( rc != 0 && rc != LDAP_OTHER ) {
+		/*
+		 * either there is no postOp (search) plugins
+		 * or a plugin failed. Just log it
+		 *
+		 * FIXME: is this correct?
+		 */
+#ifdef NEW_LOGGING
+		LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_search: search postOps failed\n"));
+#else
+		Debug (LDAP_DEBUG_TRACE, " search postOps failed.\n", 0, 0, 0);
+#endif
+    }
+#endif /* defined( LDAP_SLAPI ) */
+
 return_results:;
 #ifdef LDAP_CLIENT_UPDATE
 	if ( !( op->o_clientupdate_type & SLAP_LCUP_PERSIST ) )
diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h
index 1e611159c1..a763f6c4ee 100644
--- a/servers/slapd/slap.h
+++ b/servers/slapd/slap.h
@@ -1327,6 +1327,8 @@ struct slap_backend_db {
 	BerVarray	be_update_refs;	/* where to refer modifying clients to */
 	char	*be_realm;
 	void	*be_private;	/* anything the backend database needs 	   */
+
+	void    *be_pb;         /* Netscape plugin */
 };
 
 struct slap_conn;
@@ -1689,6 +1691,9 @@ typedef struct slap_op {
 
 	LDAP_STAILQ_ENTRY(slap_op)	o_next;	/* next operation in list	  */
 	ValuesReturnFilter *vrFilter; /* Structure represents ValuesReturnFilter */
+
+	void    *o_pb;                  /* Netscape plugin */
+
 } Operation;
 
 #define get_manageDSAit(op)				((int)(op)->o_managedsait)
@@ -1697,6 +1702,80 @@ typedef struct slap_op {
 #define get_pagedresults(op)			((int)(op)->o_pagedresults)
 
 
+
+typedef void (*SEND_LDAP_RESULT)(
+				struct slap_conn *conn,
+				struct slap_op *op,
+				ber_int_t err,
+				const char *matched,
+				const char *text,
+				BerVarray ref,
+				LDAPControl **ctrls
+				);
+
+#define send_ldap_result( conn, op, err, matched, text, ref, ctrls  ) \
+(*conn->c_send_ldap_result)( conn, op, err, matched, text, ref, ctrls )
+
+
+typedef int (*SEND_SEARCH_ENTRY)(
+				struct slap_backend_db *be,
+				struct slap_conn *conn,
+				struct slap_op *op,
+				struct slap_entry *e,
+				AttributeName *attrs,
+				int attrsonly,
+				LDAPControl **ctrls
+				);
+
+#define send_search_entry( be, conn, op, e, attrs, attrsonly, ctrls) \
+(*conn->c_send_search_entry)( be, conn, op, e, attrs, attrsonly, ctrls)
+
+
+typedef void (*SEND_SEARCH_RESULT)(
+				struct slap_conn *conn,
+				struct slap_op *op,
+				ber_int_t err,
+				const char *matched,
+				const char *text,
+				BerVarray   refs,
+				LDAPControl **ctrls,
+				int nentries
+				);
+
+#define send_search_result( conn, op, err, matched, text, refs, ctrls, nentries ) \
+(*conn->c_send_search_result)( conn, op, err, matched, text, refs, ctrls, nentries )
+
+
+typedef int (*SEND_SEARCH_REFERENCE)(
+				struct slap_backend_db *be,
+				struct slap_conn *conn,
+				struct slap_op *op,
+				struct slap_entry *e,
+				BerVarray refs,
+				LDAPControl **ctrls,
+				BerVarray *v2refs
+				);
+
+#define send_search_reference( be, conn, op, e,  refs, ctrls, v2refs ) \
+(*conn->c_send_search_reference)( be, conn, op, e,  refs, ctrls, v2refs )
+
+
+typedef void (*SEND_LDAP_EXTENDED)(
+				struct slap_conn *conn,
+				struct slap_op *op,
+				ber_int_t   err,
+				const char  *matched,
+				const char  *text,
+				BerVarray   refs,
+				const char      *rspoid,
+				struct berval *rspdata,
+				LDAPControl **ctrls
+				);
+
+#define send_ldap_extended( conn, op, err, matched, text, refs, rspoid, rspdata, ctrls) \
+(*conn->c_send_ldap_extended)( conn, op, err, matched, text, refs, rspoid, rspdata, ctrls )
+
+
 /*
  * Caches the result of a backend_group check for ACL evaluation
  */
@@ -1777,6 +1856,20 @@ typedef struct slap_conn {
 	long	c_n_get;		/* num of get calls */
 	long	c_n_read;		/* num of read calls */
 	long	c_n_write;		/* num of write calls */
+
+	void    *c_pb;                  /* Netscape plugin */
+
+    /*
+	 * These are the "callbacks" that are available for back-ends to
+	 * supply data back to connected clients that are connected
+	 * through the "front-end".
+	*/
+	SEND_LDAP_RESULT c_send_ldap_result;
+	SEND_SEARCH_ENTRY c_send_search_entry;
+	SEND_SEARCH_RESULT c_send_search_result;
+	SEND_SEARCH_REFERENCE c_send_search_reference;
+	SEND_LDAP_EXTENDED c_send_ldap_extended;
+	
 } Connection;
 
 #if defined(LDAP_SYSLOG) && defined(LDAP_DEBUG)
diff --git a/servers/slapd/slapi/Makefile.in b/servers/slapd/slapi/Makefile.in
new file mode 100644
index 0000000000..f66c2cfa43
--- /dev/null
+++ b/servers/slapd/slapi/Makefile.in
@@ -0,0 +1,45 @@
+## Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+## COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+
+## (C) Copyright IBM Corp. 1997,2002
+## Redistribution and use in source and binary forms are permitted
+## provided that this notice is preserved and that due credit is 
+## given to IBM Corporation. This software is provided ``as is'' 
+## without express or implied warranty.
+
+
+LIBRARY = libslapi.la
+XLIBRARY = libtmpslapd.a
+
+#all-common: $(LIBRARY) $(PROGRAMS)
+#	@touch plugin.c slapi_pblock.c slapi_utils.c slapi_ops.c
+
+NT_SRCS = nt_err.c
+NT_OBJS = nt_err.lo
+
+LIB_DEFS = -DSLAPI_LIBRARY
+
+SRCS=  plugin.c slapi_pblock.c slapi_utils.c printmsg.c slapi_ops.c  $(@PLAT@_SRCS)
+OBJS=  plugin.lo slapi_pblock.lo slapi_utils.lo printmsg.lo slapi_ops.lo $(@PLAT@_SRCS)
+
+XSRCS= version.c
+
+LDAP_INCDIR= ../../../include -I.. -I.       
+LDAP_LIBDIR= ../../../libraries       
+
+XLIBS = $(LIBRARY)
+XXLIBS = 
+NT_LINK_LIBS = $(AC_LIBS)
+
+XDEFS = $(MODULES_CPPFLAGS)
+
+UNIX_LINK_LIBS = ./libtmpslapd.a ../libbackends.a ../../../libraries/libavl/libavl.a ../../../libraries/liblber/.libs/liblber.a ../../../libraries/libldbm/libldbm.a ../../../libraries/libldif/libldif.a ../../../libraries/liblutil/liblutil.a ../../../libraries/liblunicode/liblunicode.a ../../../libraries/libldap_r/.libs/libldap_r.a ./libtmpslapd.a
+
+BUILD_MOD = @BUILD_SLAPI@
+
+install-local: FORCE
+	if test "$(BUILD_MOD)" = "yes"; then \
+		$(MKDIR) $(DESTDIR)$(libdir); \
+		$(LTINSTALL) $(INSTALLFLAGS) -m 644 $(LIBRARY) $(DESTDIR)$(libdir); \
+	fi
+
diff --git a/servers/slapd/slapi/README b/servers/slapd/slapi/README
new file mode 100644
index 0000000000..5edb84edd4
--- /dev/null
+++ b/servers/slapd/slapi/README
@@ -0,0 +1,55 @@
+Files included in this patch:
+
+I. Modified OpenLDAP files
+---------------------------------
+
+1.  top level configure.in				
+2.  slap.h						
+3.  back-ldbm/Makefile.in				
+4.  back-ldbm/config.c					
+5.  back-bdb/Makefile.in					
+6.  back-bdb/config.c					
+7.  slapd/tools/Makefile.in
+8.  ldap/include/Makefile.in				
+9.  slapd/Makefile.in					
+10. operation.c						
+11. root_dse.c						
+12. extended.c						
+13. bind.c						
+14. backend.c						
+15. add.c						
+16. delete.c						
+17. compare.c						
+18. moddify.c
+19. modrdn.c						
+20. search.c						
+21. result.c
+22. mimic.c
+
+
+II. New files 
+-------------------------------
+
+1. slapd/slapi/Makefile.in				
+2. slapd/slapi/ldapload.h				
+3. slapd/slapi/ldapload.c				
+4. slapd/slapi/plugin.h					
+5. slapd/slapi/plugin.c					
+6. slapd/slapi/printmsg.c				  
+7. slapd/slapi/slapi_pblock.h				
+8. slapd/slapi/slapi_pblock.c				  
+9. slapd/slapi/slapi_ops.h				
+10.slapd/slapi/slapi_utils.h				
+11.slapd/slapi/slapi_utils.c				
+12.slapd/slapi/ibm_pblock_params.h			  
+13.slapd/slapi/slapi_common.h				
+14.slapd/slapi/slapi.h					
+15.slapd/slapi/slapi_cl.h				  
+16.ldap/include/slapi-plugin.h				  
+
+III. General procedure
+
+The directory ldap/servers/slapd/slapi should be created and
+files 1-15, section II above should be placed in that directory. 
+The file slapi-plugin.h (16 above) should also be copied into 
+the ldap/include directory.
diff --git a/servers/slapd/slapi/ibm_pblock_params.h b/servers/slapd/slapi/ibm_pblock_params.h
new file mode 100644
index 0000000000..13be5fda86
--- /dev/null
+++ b/servers/slapd/slapi/ibm_pblock_params.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ * (C) Copyright IBM Corp. 1997,2002
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is 
+ * given to IBM Corporation. This software is provided ``as is'' 
+ * without express or implied warranty.
+ */
+
+#ifndef _ibm_pblock_params_H
+#define _ibm_pblock_params_H
+
+#define FIRST_PARAM -1
+#define LAST_IBM_PARAM -48
+#define NETSCAPE_RESERVED(p) (p >= 280) && (p <= 299)
+#define IBM_RESERVED(p) (p >= LAST_IBM_PARAM) && (p <= FIRST_PARAM)
+
+#define SLAPI_IBM_THREAD_CONTROL					(FIRST_PARAM - 1)
+#define SLAPI_IBM_PBLOCK							(FIRST_PARAM - 2)
+#define SLAPI_IBM_CONNECTION_PTR					(FIRST_PARAM - 3)
+#define SLAPI_IBM_BACKENDS							(FIRST_PARAM - 4)
+#define SLAPI_PRE_BIND_ALL							(FIRST_PARAM - 5)
+#define SLAPI_POST_BIND_ALL							(FIRST_PARAM - 6)
+#define SLAPI_IBM_ADMIN_DN							(FIRST_PARAM - 7)
+#define SLAPI_CONFIG_STATE							(FIRST_PARAM - 8)
+#define SLAPI_PLUGIN_DB_REGISTER_SERVICE_FN			(FIRST_PARAM - 9)   
+#define SLAPI_PLUGIN_DB_INSERT_REPL_ENTRIES_FN		(FIRST_PARAM - 10)
+#define SLAPI_PLUGIN_DB_GET_REPL_ENTRIES_FN			(FIRST_PARAM - 11)
+#define SLAPI_PLUGIN_DB_REPLICA_DONE_FN				(FIRST_PARAM - 12)
+#define SLAPI_PLUGIN_DB_INIT_REPL_LIST_FN			(FIRST_PARAM - 13)
+#define SLAPI_PLUGIN_DB_THREAD_INITIALIZE_FN		(FIRST_PARAM - 14)
+#define SLAPI_PLUGIN_DB_THREAD_TERMINATE_FN			(FIRST_PARAM - 15)
+#define SLAPI_PLUGIN_DB_SCHEMA_MODIFY_ATTRTYPE_FN	(FIRST_PARAM - 16)
+#define SLAPI_PLUGIN_DB_SCHEMA_MODIFY_OBJCLASS_FN	(FIRST_PARAM - 17)
+#define SLAPI_PLUGIN_DB_INIT_FN						(FIRST_PARAM - 18)
+#define SLAPI_IBM_EXTENDED_OPS						(FIRST_PARAM - 19)
+#define SLAPI_IBM_CONTROLS							(FIRST_PARAM - 20)
+#define SLAPI_IBM_SASLMECHANISMS					(FIRST_PARAM - 21)
+#define SLAPI_IBM_BROADCAST_BE						(FIRST_PARAM - 22)
+#define SLAPI_IBM_NOTIFY_BIND_FN					(FIRST_PARAM - 23)
+#define SLAPI_IBM_SECRET							(FIRST_PARAM - 24)
+#define SLAPI_IBM_CL_START_FN						(FIRST_PARAM - 25)
+#define SLAPI_IBM_REPLICATE							(FIRST_PARAM - 26)
+#define SLAPI_IBM_CL_CLASS							(FIRST_PARAM - 27)
+#define SLAPI_IBM_CL_SUFFIX							(FIRST_PARAM - 28)
+#define SLAPI_IBM_CL_MAX_ENTRIES					(FIRST_PARAM - 29)
+#define SLAPI_IBM_CONNINFO							(FIRST_PARAM - 30)
+#define SLAPI_IBM_CL_FIRST_ENTRY					(FIRST_PARAM - 31)
+#define SLAPI_IBM_CL_LAST_ENTRY						(FIRST_PARAM - 32)
+#define SLAPI_IBM_CONN_DN_ALT						(FIRST_PARAM - 33)
+#define SLAPI_IBM_GSSAPI_CONTEXT					(FIRST_PARAM - 34)
+#define SLAPI_IBM_ADD_ENTRY							(FIRST_PARAM - 35)
+#define SLAPI_IBM_DELETE_ENTRY						(FIRST_PARAM - 36)
+#define SLAPI_IBM_MODIFY_ENTRY						(FIRST_PARAM - 37)
+#define SLAPI_IBM_MODIFY_MODS						(FIRST_PARAM - 38)
+#define SLAPI_IBM_MODRDN_ENTRY						(FIRST_PARAM - 39)
+#define SLAPI_IBM_MODRDN_NEWDN						(FIRST_PARAM - 40)
+#define SLAPI_IBM_EVENT_ENABLED						(FIRST_PARAM - 41)
+#define SLAPI_IBM_EVENT_MAXREG						(FIRST_PARAM - 42)
+#define SLAPI_IBM_EVENT_REGPERCONN					(FIRST_PARAM - 43)
+#define SLAPI_IBM_EVENT_CURREG						(FIRST_PARAM - 44)
+#define SLAPI_IBM_EVENT_SENTREG						(FIRST_PARAM - 45)
+#define SLAPI_IBM_CONN_DN_ORIG						(FIRST_PARAM - 46)
+#define SLAPI_PLUGIN_DB_DELETE_PROGRESS_FN			(FIRST_PARAM - 47) 
+#endif
diff --git a/servers/slapd/slapi/plugin.c b/servers/slapd/slapi/plugin.c
new file mode 100644
index 0000000000..858cbeb37e
--- /dev/null
+++ b/servers/slapd/slapi/plugin.c
@@ -0,0 +1,679 @@
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ * (C) Copyright IBM Corp. 1997,2002
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is 
+ * given to IBM Corporation. This software is provided ``as is'' 
+ * without express or implied warranty.
+ */
+
+#include "portable.h"
+#include "slapi_common.h"
+#include <ldap_pvt_thread.h>
+#include <slap.h>
+#include <slapi.h>
+
+/*
+ * Note: if ltdl.h is not available, slapi should not be compiled
+ */
+#include <ltdl.h>
+
+static int loadPlugin( Slapi_PBlock *, const char *, const char *, int, 
+	SLAPI_FUNC *, lt_dlhandle * );
+
+/* pointer to link list of extended objects */
+static ExtendedOp *pGExtendedOps = NULL;
+
+/*********************************************************************
+ * Function Name:      newPlugin
+ *
+ * Description:        This routine creates a new Slapi_PBlock structure,
+ *                     loads in the plugin module and executes the init
+ *                     function provided by the module.
+ *
+ * Input:              type - type of the plugin, such as SASL, database, etc.
+ *                     path - the loadpath to load the module in
+ *                     initfunc - name of the plugin function to execute first
+ *                     argc - number of arguements
+ *                     argv[] - an array of char pointers point to
+ *                              the arguments passed in via
+ *                              the configuration file.
+ *
+ * Output:             
+ *
+ * Return Values:      a pointer to a newly created Slapi_PBlock structrue or
+ *                     NULL - function failed 
+ *
+ * Messages:           None
+ *********************************************************************/
+
+Slapi_PBlock *
+newPlugin(
+	int type, 
+	const char *path, 
+	const char *initfunc, 
+	int argc, 
+	char *argv[] ) 
+{
+	Slapi_PBlock	*pPlugin = NULL; 
+	lt_dlhandle	hdLoadHandle;
+	int		rc;
+
+	pPlugin = slapi_pblock_new();
+	if ( pPlugin == NULL ) {
+		rc = LDAP_NO_MEMORY;
+		goto done;
+	}
+
+	rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_TYPE, (void *)type );
+	if ( rc != LDAP_SUCCESS ) {
+		goto done;
+	}
+
+	rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_ARGC, (void *)argc );
+	if ( rc != LDAP_SUCCESS ) {
+		goto done;
+	}
+
+	rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_ARGV, (void *)argv );
+	if ( rc != LDAP_SUCCESS ) { 
+		goto done;
+	}
+
+	rc = loadPlugin( pPlugin, path, initfunc, TRUE, NULL, &hdLoadHandle );
+
+done:
+	if ( rc != LDAP_SUCCESS && pPlugin != NULL ) {
+		slapi_pblock_destroy( pPlugin );
+		pPlugin = NULL;
+	}
+
+	return pPlugin;
+} 
+
+/*********************************************************************
+ * Function Name:      insertPlugin
+ *
+ * Description:        insert the slapi_pblock structure to the end of the plugin
+ *                     list 
+ *
+ * Input:              a pointer to a plugin slapi_pblock structure to be added to 
+ *                     the list
+ *
+ * Output:             none
+ *
+ * Return Values:      LDAP_SUCCESS - successfully inserted.
+ *                     LDAP_LOCAL_ERROR.
+ *
+ * Messages:           None
+ *********************************************************************/
+int 
+insertPlugin(
+	Backend *be, 
+	Slapi_PBlock *pPB )
+{ 
+	Slapi_PBlock *pTmpPB;
+	Slapi_PBlock *pSavePB;
+	int    rc = LDAP_SUCCESS;
+
+	pTmpPB = (Slapi_PBlock *)(be->be_pb);
+       
+	if ( pTmpPB == NULL ) {
+		be->be_pb = (void *)pPB;
+	} else {
+		while ( pTmpPB != NULL && rc == LDAP_SUCCESS ) {
+			pSavePB = pTmpPB;
+			rc = slapi_pblock_get( pTmpPB, SLAPI_IBM_PBLOCK,
+					&pTmpPB );
+			if ( rc != LDAP_SUCCESS ) {
+				rc = LDAP_OTHER;
+			}
+		}
+
+		if ( rc == LDAP_SUCCESS ) { 
+			rc = slapi_pblock_set( pSavePB, SLAPI_IBM_PBLOCK,
+					(void *)pPB ); 
+			if ( rc != LDAP_SUCCESS ) {
+				rc = LDAP_OTHER;
+			}
+		}
+	}
+     
+	return rc;
+}
+       
+/*********************************************************************
+ * Function Name:      getAllPluginFuncs
+ *
+ * Description:        get the desired type of function pointers defined 
+ *                     in all the plugins 
+ *
+ * Input:              the type of the functions to get, such as pre-operation,etc.
+ *
+ * Output:             none
+ *
+ * Return Values:      this routine returns a pointer to an array of function
+ *                     pointers
+ *
+ * Messages:           None
+ *********************************************************************/
+int 
+getAllPluginFuncs(
+	Backend *be, 		
+	int functype, 
+	SLAPI_FUNC **ppFuncPtrs )
+{
+ 
+	Slapi_PBlock	*pCurrentPB; 
+	SLAPI_FUNC	FuncPtr;
+	SLAPI_FUNC	*pTmpFuncPtr;
+	int		numPB = 0;
+	int		rc = LDAP_SUCCESS;
+
+	assert( be );
+	assert( ppFuncPtrs );
+
+	pCurrentPB = (Slapi_PBlock *)(be->be_pb);
+     
+	if ( pCurrentPB == NULL ) { 
+		/*
+		 * LDAP_OTHER is returned if no plugins are installed
+		 */
+		rc = LDAP_OTHER;
+		goto done;
+	}
+
+	while ( pCurrentPB != NULL && rc == LDAP_SUCCESS ) {
+		rc = slapi_pblock_get( pCurrentPB, functype, &FuncPtr );
+		if ( rc == LDAP_SUCCESS ) {
+			if ( FuncPtr != NULL )  {
+				numPB++;
+			}
+			rc = slapi_pblock_get( pCurrentPB,
+					SLAPI_IBM_PBLOCK, &pCurrentPB );
+		}
+	}
+
+	if ( rc != LDAP_SUCCESS ) {
+		goto done;
+	}
+
+	if ( numPB == 0 ) {
+		*ppFuncPtrs = NULL;
+		rc = LDAP_SUCCESS;
+		goto done;
+	}
+
+	*ppFuncPtrs = pTmpFuncPtr = 
+		(SLAPI_FUNC *)ch_malloc( ( numPB + 1 ) * sizeof(SLAPI_FUNC) ); 
+	if ( ppFuncPtrs == NULL ) {
+		rc = LDAP_NO_MEMORY;
+		goto done;
+	}
+
+	pCurrentPB = (Slapi_PBlock *)(be->be_pb);
+	while ( pCurrentPB != NULL && rc == LDAP_SUCCESS )  {
+		rc = slapi_pblock_get( pCurrentPB, functype, &FuncPtr );
+		if ( rc == LDAP_SUCCESS ) {
+			if ( FuncPtr != NULL )  {
+				*pTmpFuncPtr = FuncPtr;
+				pTmpFuncPtr++;
+			} 
+			rc = slapi_pblock_get( pCurrentPB,
+					SLAPI_IBM_PBLOCK, &pCurrentPB );
+		}
+	}
+	*pTmpFuncPtr = NULL ;
+
+done:
+	if ( rc != LDAP_SUCCESS && *ppFuncPtrs != NULL ) {
+		ch_free( *ppFuncPtrs );
+		*ppFuncPtrs = NULL;
+	}
+
+	return rc;
+}
+              
+/*********************************************************************
+ * Function Name:      createExtendedOp
+ *
+ * Description: Creates an extended operation structure and
+ *              initializes the fields
+ *
+ * Return value: A newly allocated structure or NULL
+ ********************************************************************/
+ExtendedOp *
+createExtendedOp()
+{
+	ExtendedOp *ret;
+
+	ret = (ExtendedOp *)ch_malloc(sizeof(ExtendedOp));
+	if ( ret != NULL ) {
+		ret->ext_oid.bv_val = NULL;
+		ret->ext_oid.bv_len = 0;
+		ret->ext_func = NULL;
+		ret->ext_be = NULL;
+		ret->ext_next = NULL;
+	}
+
+	return ret;
+}
+
+
+/*********************************************************************
+ * Function Name:      removeExtendedOp
+ *
+ * Description:        This routine removes the ExtendedOp structures 
+ *					   asscoiated with a particular extended operation 
+ *					   plugin.
+ *
+ * Input:              pBE - pointer to a backend structure
+ *                     opList - pointer to a linked list of extended
+ *                              operation structures
+ *                     pPB - pointer to a slapi parameter block
+ *
+ * Output:
+ *
+ * Return Value:       none
+ *
+ * Messages:           None
+ *********************************************************************/
+void
+removeExtendedOp(
+	Backend *pBE, 
+	ExtendedOp **opList, 
+	Slapi_PBlock *pPB )
+{
+	ExtendedOp	*pTmpExtOp, *backExtOp;
+	char		**pTmpOIDs;
+	int		i;
+
+#if 0
+	assert( pBE != NULL); /* unused */
+#endif /* 0 */
+	assert( opList != NULL );
+	assert( pPB != NULL );
+
+	if ( *opList == NULL ) {
+		return;
+	}
+
+	slapi_pblock_get( pPB, SLAPI_PLUGIN_EXT_OP_OIDLIST, &pTmpOIDs );
+	if ( pTmpOIDs == NULL ) {
+		return;
+	}
+
+	for ( i = 0; pTmpOIDs[i] != NULL; i++ ) {
+		backExtOp = NULL;
+		pTmpExtOp = *opList;
+		for ( ; pTmpExtOp != NULL; pTmpExtOp = pTmpExtOp->ext_next) {
+			int	rc;
+			rc = strcasecmp( pTmpExtOp->ext_oid.bv_val,
+					pTmpOIDs[ i ] );
+			if ( rc == 0 ) {
+				if ( backExtOp == NULL ) {
+					*opList = pTmpExtOp->ext_next;
+				} else {
+					backExtOp->ext_next
+						= pTmpExtOp->ext_next;
+				}
+
+				ch_free( pTmpExtOp );
+				break;
+			}
+			backExtOp = pTmpExtOp;
+		}
+	}
+}
+
+
+/*********************************************************************
+ * Function Name:      newExtendedOp
+ *
+ * Description:        This routine creates a new ExtendedOp structure, loads
+ *                     in the extended op module and put the extended op function address
+ *                     in the structure. The function will not be executed in
+ *                     this routine.
+ *
+ * Input:              pBE - pointer to a backend structure
+ *                     opList - pointer to a linked list of extended
+ *                              operation structures
+ *                     pPB - pointer to a slapi parameter block
+ *
+ * Output:
+ *
+ * Return Value:       an LDAP return code
+ *
+ * Messages:           None
+ *********************************************************************/
+int 
+newExtendedOp(
+	Backend *pBE, 	
+	ExtendedOp **opList, 
+	Slapi_PBlock *pPB )
+{
+	ExtendedOp	*pTmpExtOp = NULL;
+	SLAPI_FUNC	tmpFunc;
+	char		**pTmpOIDs;
+	int		rc = LDAP_OTHER;
+	int		i;
+
+	if ( (*opList) == NULL ) { 
+		*opList = createExtendedOp();
+		if ( (*opList) == NULL ) {
+			rc = LDAP_NO_MEMORY;
+			goto error_return;
+		}
+		pTmpExtOp = *opList;
+		
+	} else {                        /* Find the end of the list */
+		for ( pTmpExtOp = *opList; pTmpExtOp->ext_next != NULL;
+				pTmpExtOp = pTmpExtOp->ext_next )
+			; /* EMPTY */
+		pTmpExtOp->ext_next = createExtendedOp();
+		if ( pTmpExtOp->ext_next == NULL ) {
+			rc = LDAP_NO_MEMORY;
+			goto error_return;
+		}
+		pTmpExtOp = pTmpExtOp->ext_next;
+	}
+
+	rc = slapi_pblock_get( pPB,SLAPI_PLUGIN_EXT_OP_OIDLIST, &pTmpOIDs );
+	if ( rc != LDAP_SUCCESS ) {
+		rc = LDAP_OTHER;
+		goto error_return;
+	}
+
+	rc = slapi_pblock_get(pPB,SLAPI_PLUGIN_EXT_OP_FN, &tmpFunc);
+	if ( rc != 0 ) {
+		rc = LDAP_OTHER;
+		goto error_return;
+	}
+
+	if ( (pTmpOIDs == NULL) || (tmpFunc == NULL) ) {
+		rc = LDAP_OTHER;
+		goto error_return;
+	}
+
+	for ( i = 0; pTmpOIDs[i] != NULL; i++ ) {
+		pTmpExtOp->ext_oid.bv_val = pTmpOIDs[i];
+		pTmpExtOp->ext_oid.bv_len = strlen( pTmpOIDs[i] );
+		pTmpExtOp->ext_func = tmpFunc;
+		pTmpExtOp->ext_be = pBE;
+		if ( pTmpOIDs[i + 1] != NULL ) {
+			pTmpExtOp->ext_next = createExtendedOp();
+			if ( pTmpExtOp->ext_next == NULL ) {
+				rc = LDAP_NO_MEMORY;
+				break;
+			}
+			pTmpExtOp = pTmpExtOp->ext_next;
+		}
+	}
+
+error_return:
+	return rc;
+}
+
+/*********************************************************************
+ * Function Name:      getPluginFunc
+ *
+ * Description:        This routine gets the function address for a given function
+ *                     name.
+ *
+ * Input:
+ *                     funcName - name of the extended op function, ie. an OID.
+ *
+ * Output:             pFuncAddr - the function address of the requested function name.
+ *
+ * Return Values:      a pointer to a newly created ExtendOp structrue or
+ *                     NULL - function failed
+ *
+ * Messages:           None
+ *********************************************************************/
+int 
+getPluginFunc(
+	struct berval *reqoid, 		
+	SLAPI_FUNC *pFuncAddr ) 
+{
+	ExtendedOp	*pTmpExtOp;
+
+	assert( reqoid != NULL );
+	assert( pFuncAddr != NULL );
+
+	*pFuncAddr = NULL;
+
+	if ( pGExtendedOps == NULL ) {
+		return LDAP_OTHER;
+	}
+
+	pTmpExtOp = pGExtendedOps;
+	while ( pTmpExtOp != NULL ) {
+		int	rc;
+		
+		rc = strcasecmp( reqoid->bv_val, pTmpExtOp->ext_oid.bv_val );
+		if ( rc == 0 ) {
+			*pFuncAddr = pTmpExtOp->ext_func;
+			break;
+		}
+		pTmpExtOp = pTmpExtOp->ext_next;
+	}
+
+	return ( *pFuncAddr == NULL ? 1 : 0 );
+}
+
+/***************************************************************************
+ * This function is similar to getPluginFunc above. except it returns one OID
+ * per call. It is called from root_dse_info (root_dse.c).
+ * The function is a modified version of get_supported_extop (file extended.c).
+ ***************************************************************************/
+struct berval *
+ns_get_supported_extop( int index )
+{
+        ExtendedOp	*ext;
+
+        for ( ext = pGExtendedOps ; ext != NULL && --index >= 0;
+			ext = ext->ext_next) {
+                ; /* empty */
+        }
+
+        if ( ext == NULL ) {
+		return NULL;
+	}
+
+        return &ext->ext_oid ;
+}
+
+/*********************************************************************
+ * Function Name:      loadPlugin
+ *
+ * Description:        This routine loads the specified DLL, gets and executes the init function
+ *                     if requested.
+ *
+ * Input:
+ *                     pPlugin - a pointer to a Slapi_PBlock struct which will be passed to
+ *                               the DLL init function.
+ *                     path - path name of the DLL to be load.
+ *                     initfunc - either the DLL initialization function or an OID of the
+ *                                loaded extended operation.
+ *                     doInit - if it is TRUE, execute the init function, otherwise, save the
+ *                              function address but not execute it.
+ *
+ * Output:             pInitFunc - the function address of the loaded function. This param
+ *                                 should be not be null if doInit is FALSE.
+ *                     pLdHandle - handle returned by lt_dlopen()
+ *
+ * Return Values:      LDAP_SUCCESS, LDAP_LOCAL_ERROR
+ *
+ * Messages:           None
+ *********************************************************************/
+
+static int 
+loadPlugin(
+	Slapi_PBlock	*pPlugin,
+	const char	*path,
+	const char	*initfunc, 
+	int		doInit,
+	SLAPI_FUNC	*pInitFunc,
+	lt_dlhandle	*pLdHandle ) 
+{
+	int		rc = LDAP_SUCCESS;
+	SLAPI_FUNC	fpInitFunc = NULL;
+
+	assert( pLdHandle );
+
+	if ( lt_dlinit() ) {
+		return LDAP_LOCAL_ERROR;
+	}
+
+	/* load in the module */
+	*pLdHandle = lt_dlopen( path );
+	if ( *pLdHandle == NULL ) {
+		return LDAP_LOCAL_ERROR;
+	}
+
+	fpInitFunc = (SLAPI_FUNC)lt_dlsym( *pLdHandle, initfunc );
+	if ( fpInitFunc == NULL ) {
+		lt_dlclose( *pLdHandle );
+		return LDAP_LOCAL_ERROR;
+	}
+
+	if ( doInit == TRUE ) {
+		rc = ( *fpInitFunc )( pPlugin );
+		if ( rc != LDAP_SUCCESS ) {
+			lt_dlclose( *pLdHandle );
+		}
+
+	} else {
+		*pInitFunc = fpInitFunc;
+	}
+
+	return rc;
+}
+
+
+int 
+doPluginFNs(
+	Backend		*be, 	
+	int		funcType, 
+	Slapi_PBlock	*pPB )
+{
+
+	int rc = LDAP_SUCCESS;
+	SLAPI_FUNC *pGetPlugin = NULL, *tmpPlugin = NULL; 
+
+	rc = getAllPluginFuncs(be, funcType, &tmpPlugin );
+	if ( rc != LDAP_SUCCESS || tmpPlugin == NULL ) {
+		return rc;
+	}
+
+	for ( pGetPlugin = tmpPlugin ; *pGetPlugin != NULL; pGetPlugin++ ) {
+		/*
+		 * FIXME: operation stops at first non-success
+		 *
+		 * FIXME: we should provide here a sort of sandbox,
+		 * to protect from plugin faults; e.g. trap signals
+		 * and longjump here, marking the plugin as unsafe for
+		 * later executions ...
+		 */
+		rc = (*pGetPlugin)(pPB);
+
+		if ( rc != LDAP_SUCCESS ) {
+			break;
+		}
+	}
+
+	ch_free( tmpPlugin );
+
+	return rc;
+}
+
+int
+netscape_plugin(
+	Backend		*be, 		
+	const char	*fname, 
+	int		lineno, 
+	int		argc, 
+	char		**argv )
+{
+	int		iType = -1;
+	int		numPluginArgc = 0;
+	char		**ppPluginArgv = NULL;
+
+	if ( argc < 4 ) {
+		fprintf( stderr,
+			"%s: line %d: missing arguments "
+			"in \"plugin <plugin_type> <lib_path> "
+			"<init_function> [<arguments>]\" line\n",
+			fname, lineno );
+		return 1;
+	}
+	
+	if ( strcasecmp( argv[1], "preoperation" ) == 0 ) {
+		iType = SLAPI_PLUGIN_PREOPERATION;
+	} else if ( strcasecmp( argv[1], "postoperation" ) == 0 ) {
+		iType = SLAPI_PLUGIN_POSTOPERATION;
+	} else if ( strcasecmp( argv[1], "extendedop" ) == 0 ) {
+		iType = SLAPI_PLUGIN_EXTENDEDOP;
+	} else {
+		fprintf( stderr, "%s: line %d: invalid plugin type \"%s\".\n",
+				fname, lineno, argv[1] );
+		return 1;
+	}
+	
+	numPluginArgc = argc - 4;
+	if ( numPluginArgc > 0 ) {
+		ppPluginArgv = &argv[4];
+	} else {
+		ppPluginArgv = NULL;
+	}
+
+	if ( iType == SLAPI_PLUGIN_PREOPERATION ||
+		  	iType == SLAPI_PLUGIN_EXTENDEDOP ||
+			iType == SLAPI_PLUGIN_POSTOPERATION ) {
+		int rc;
+		Slapi_PBlock *pPlugin;
+
+		pPlugin = newPlugin( iType, argv[2], argv[3], 
+					numPluginArgc, ppPluginArgv );
+		if (pPlugin == NULL) {
+			return 1;
+		}
+
+		if (iType == SLAPI_PLUGIN_EXTENDEDOP) {
+			rc = newExtendedOp(be, &pGExtendedOps, pPlugin);
+			if ( rc != LDAP_SUCCESS ) {
+				slapi_pblock_destroy( pPlugin );
+				return 1;
+			}
+		}
+
+		rc = insertPlugin( be, pPlugin );
+		if ( rc != LDAP_SUCCESS ) {
+			if ( iType == SLAPI_PLUGIN_EXTENDEDOP ) {
+				removeExtendedOp( be, &pGExtendedOps, pPlugin );
+			}
+			slapi_pblock_destroy( pPlugin );
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+int
+slapi_init(void)
+{
+	if ( ldap_pvt_thread_mutex_init( &slapi_hn_mutex ) ) {
+		return -1;
+	}
+	
+	if ( ldap_pvt_thread_mutex_init( &slapi_time_mutex ) ) {
+		return -1;
+	}
+
+	return 0;
+}
+
diff --git a/servers/slapd/slapi/plugin.h b/servers/slapd/slapi/plugin.h
new file mode 100644
index 0000000000..7aaa20ef60
--- /dev/null
+++ b/servers/slapd/slapi/plugin.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ * (C) Copyright IBM Corp. 1997,2002
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is 
+ * given to IBM Corporation. This software is provided ``as is'' 
+ * without express or implied warranty.
+ */
+
+#ifndef _PLUGIN_H_ 
+#define _PLUGIN_H_ 
+
+Slapi_PBlock *newPlugin ( int type, const char *path, const char *initfunc,
+		int argc, char *argv[] );
+int insertPlugin(Backend *be, Slapi_PBlock *pPB);
+int doPluginFNs(Backend *be, int funcType, Slapi_PBlock * pPB);
+int getAllPluginFuncs(Backend *be, int functype, SLAPI_FUNC **ppFuncPtrs);
+int newExtendedOp(Backend *pBE, ExtendedOp **opList, Slapi_PBlock *pPB);
+int getPluginFunc(struct berval  *reqoid, SLAPI_FUNC *pFuncAddr );
+int netscape_plugin(Backend *be, const char *fname, int lineno,
+		int argc, char **argv );
+int slapi_init(void);
+
+#endif /* _PLUGIN_H_ */
+
diff --git a/servers/slapd/slapi/printmsg.c b/servers/slapd/slapi/printmsg.c
new file mode 100644
index 0000000000..6ecdadc3a8
--- /dev/null
+++ b/servers/slapd/slapi/printmsg.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ * (C) Copyright IBM Corp. 1997,2002
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is 
+ * given to IBM Corporation. This software is provided ``as is'' 
+ * without express or implied warranty.
+ */
+
+#include <portable.h>
+#include <slapi_common.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <ldap.h>
+#include <ldap_config.h>
+#include <slap.h>
+#include <slapi.h>
+
+#include <ldap_pvt_thread.h>
+
+/* Single threads access to routine */
+static ldap_pvt_thread_mutex_t PrintMessage_mutex; 
+static int PrintMessage_mutex_inited = 0;
+
+static void
+InitMutex () 
+{
+	if (PrintMessage_mutex_inited == 0) {
+		PrintMessage_mutex_inited = 1;
+		ldap_pvt_thread_mutex_init(&PrintMessage_mutex);
+	}
+}
+
+int 
+vLogError(
+	int level, 	
+	char *subsystem, 
+	char *fmt, 
+	va_list arglist ) 
+{
+	int rc = 0;
+	char *tmpFmt;
+	FILE * fp = NULL;
+	char *p, *sval;
+	int ival;
+
+	char timeStr[100];
+	struct tm *ltm;
+	time_t currentTime;
+
+	tmpFmt = fmt;
+	fmt = (char*)ch_calloc(strlen(subsystem) + strlen(tmpFmt) + 3, 1);
+	sprintf(fmt, "%s: %s", subsystem, tmpFmt);
+
+	InitMutex() ;
+	ldap_pvt_thread_mutex_lock( &PrintMessage_mutex ) ;
+
+	/* for now, we log all severities */
+	if ( 1 ) {
+		fp = fopen( LDAP_RUNDIR LDAP_DIRSEP "errors", "a" );
+		if (fp == NULL) 
+			fp = fopen( "errors", "a" );
+			
+		if ( fp != NULL) {
+			while ( lockf(fileno(fp), F_LOCK, 0 ) != 0 ) {}
+
+			time (&currentTime);
+			ltm = localtime( &currentTime );
+			strftime( timeStr, sizeof(timeStr), "%x %X ", ltm );
+			fprintf(fp, timeStr);
+			for (p = fmt; *p; p++) {
+				if (*p != '%') {
+					fprintf(fp, "%c", *p);
+					continue;
+				}
+				switch(*++p) {
+				case 'd':
+					ival = va_arg( arglist, int);
+					fprintf(fp, "%d", ival);
+					break;
+				case 's':
+					for (sval = va_arg(arglist, char *); *sval; sval++)
+						fprintf(fp, "%c", *sval);
+					break;
+				default:
+					fprintf(fp, "%c", *p);
+					break;
+				
+				}
+			}
+	
+			fflush(fp);
+
+			lockf( fileno(fp), F_ULOCK, 0 );
+
+			fclose(fp);
+		} else {
+#if 0 /* unused */
+			int save_errno = (int)errno;
+#endif /* unused */
+			rc = ( -1);
+		}
+	} else {
+		rc = ( -1);
+	}
+
+	ldap_pvt_thread_mutex_unlock( &PrintMessage_mutex );
+	ch_free(fmt);
+
+	return (rc);
+}
diff --git a/servers/slapd/slapi/slapi-plugin.h b/servers/slapd/slapi/slapi-plugin.h
new file mode 100644
index 0000000000..824e1dbf95
--- /dev/null
+++ b/servers/slapd/slapi/slapi-plugin.h
@@ -0,0 +1,379 @@
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ * (C) Copyright IBM Corp. 1997,2002
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is
+ * given to IBM Corporation. This software is provided ``as is''
+ * without express or implied warranty.
+ */
+
+#ifndef _SLAPI_PLUGIN_H
+#define _SLAPI_PLUGIN_H
+
+#include "lber.h"
+#include "ldap.h"
+
+typedef struct slapi_pblock	Slapi_PBlock;
+typedef struct slapi_entry	Slapi_Entry;
+typedef struct slapi_attr	Slapi_Attr;
+typedef struct slapi_filter	Slapi_Filter;
+
+
+/* pblock routines */
+int slapi_pblock_get( Slapi_PBlock *pb, int arg, void *value );
+int slapi_pblock_set( Slapi_PBlock *pb, int arg, void *value );
+Slapi_PBlock *slapi_pblock_new();
+void slapi_pblock_destroy( Slapi_PBlock* );
+
+/* entry/attr/dn routines */
+Slapi_Entry *slapi_str2entry( char *s, int flags );
+char *slapi_entry2str( Slapi_Entry *e, int *len );
+char *slapi_entry_get_dn( Slapi_Entry *e );
+void slapi_entry_set_dn( Slapi_Entry *e, char *dn );
+Slapi_Entry *slapi_entry_dup( Slapi_Entry *e );
+int slapi_entry_attr_delete( Slapi_Entry *e, char *type );
+Slapi_Entry *slapi_entry_alloc();
+void slapi_entry_free( Slapi_Entry *e );
+int slapi_entry_attr_merge( Slapi_Entry *e, char *type, struct berval **vals );
+int slapi_entry_attr_find( Slapi_Entry *e, char *type, Slapi_Attr **attr );
+int slapi_attr_get_values( Slapi_Attr *attr, struct berval ***vals );
+char *slapi_dn_normalize( char *dn );
+char *slapi_dn_normalize_case( char *dn );
+int slapi_dn_issuffix( char *dn, char *suffix );
+char *slapi_dn_ignore_case( char *dn );
+
+/* char routines */
+char *slapi_ch_malloc( unsigned long size );
+void slapi_ch_free( void *ptr );
+char *slapi_ch_calloc( unsigned long nelem, unsigned long size );
+char *slapi_ch_realloc( char *block, unsigned long size );
+char *slapi_ch_strdup( char *s );
+
+
+/* LDAP V3 routines */
+int slapi_control_present( LDAPControl **controls, char *oid,
+	struct berval **val, int *iscritical);
+void slapi_register_supported_control(char *controloid,
+	unsigned long controlops);
+#define SLAPI_OPERATION_BIND            0x00000001L
+#define SLAPI_OPERATION_UNBIND          0x00000002L
+#define SLAPI_OPERATION_SEARCH          0x00000004L
+#define SLAPI_OPERATION_MODIFY          0x00000008L
+#define SLAPI_OPERATION_ADD             0x00000010L
+#define SLAPI_OPERATION_DELETE          0x00000020L
+#define SLAPI_OPERATION_MODDN           0x00000040L
+#define SLAPI_OPERATION_MODRDN          SLAPI_OPERATION_MODDN
+#define SLAPI_OPERATION_COMPARE         0x00000080L
+#define SLAPI_OPERATION_ABANDON         0x00000100L
+#define SLAPI_OPERATION_EXTENDED        0x00000200L
+#define SLAPI_OPERATION_ANY             0xFFFFFFFFL
+#define SLAPI_OPERATION_NONE            0x00000000L
+int slapi_get_supported_controls(char ***ctrloidsp, unsigned long **ctrlopsp);
+void slapi_register_supported_saslmechanism(char *mechanism);
+char **slapi_get_supported_saslmechanisms();
+char **slapi_get_supported_extended_ops(void);
+
+
+/* send ldap result back */
+void slapi_send_ldap_result( Slapi_PBlock *pb, int err, char *matched,
+	char *text, int nentries, struct berval **urls );
+int slapi_send_ldap_search_entry( Slapi_PBlock *pb, Slapi_Entry *e,
+	LDAPControl **ectrls, char **attrs, int attrsonly );
+
+/* filter routines */
+Slapi_Filter *slapi_str2filter( char *str );
+void slapi_filter_free( Slapi_Filter *f, int recurse );
+int slapi_filter_get_choice( Slapi_Filter *f);
+int slapi_filter_get_ava( Slapi_Filter *f, char **type, struct berval **bval );
+Slapi_Filter *slapi_filter_list_first( Slapi_Filter *f );
+Slapi_Filter *slapi_filter_list_next( Slapi_Filter *f, Slapi_Filter *fprev );
+
+/* internal add/delete/search/modify routines */
+Slapi_PBlock *slapi_search_internal( char *base, int scope, char *filter, 
+	LDAPControl **controls, char **attrs, int attrsonly );
+Slapi_PBlock *slapi_modify_internal( char *dn, LDAPMod **mods,
+        LDAPControl **controls, int log_change);
+Slapi_PBlock *slapi_add_entry_internal( Slapi_Entry * e,
+	LDAPControl **controls, int log_change );
+Slapi_PBlock *slapi_add_internal( char * dn, LDAPMod **attrs,
+	LDAPControl **controls, int log_changes );
+Slapi_PBlock *slapi_add_entry_internal( Slapi_Entry * e,
+	LDAPControl **controls, int log_change );
+Slapi_PBlock *slapi_delete_internal( char * dn,  LDAPControl **controls,
+	int log_change );
+Slapi_PBlock *slapi_modrdn_internal( char * olddn, char * newrdn,
+	char *newParent, int deloldrdn, LDAPControl **controls,
+	int log_change);
+void slapi_free_search_results_internal(Slapi_PBlock *pb);
+
+/* connection related routines */
+int slapi_is_connection_ssl(Slapi_PBlock *pPB, int *isSSL);
+int slapi_get_client_port(Slapi_PBlock *pPB, int *fromPort);
+
+/* parameters currently supported */
+
+
+/* plugin types supported */
+
+#define SLAPI_PLUGIN_DATABASE           1
+#define SLAPI_PLUGIN_EXTENDEDOP         2
+#define SLAPI_PLUGIN_PREOPERATION       3
+#define SLAPI_PLUGIN_POSTOPERATION      4
+#define SLAPI_PLUGIN_AUDIT              7   
+
+/* misc params */
+
+#define SLAPI_BACKEND				130
+#define SLAPI_CONNECTION			131
+#define SLAPI_OPERATION				132
+#define SLAPI_REQUESTOR_ISROOT			133
+#define SLAPI_BE_MONITORDN			134
+#define SLAPI_BE_TYPE           		135
+#define SLAPI_BE_READONLY       		136
+#define SLAPI_BE_LASTMOD       			137
+#define SLAPI_CONN_ID        			139
+
+/* operation params */
+#define SLAPI_OPINITIATED_TIME			140
+#define SLAPI_REQUESTOR_DN			141
+#define SLAPI_REQUESTOR_ISUPDATEDN		142
+
+/* connection  structure params*/
+#define SLAPI_CONN_DN        			143
+#define SLAPI_CONN_AUTHTYPE    			144
+
+/*  Authentication types */
+#define SLAPD_AUTH_NONE   "none"
+#define SLAPD_AUTH_SIMPLE "simple"
+#define SLAPD_AUTH_SSL    "SSL"
+#define SLAPD_AUTH_SASL   "SASL " 
+
+/* plugin configuration parmams */
+#define SLAPI_PLUGIN				3
+#define SLAPI_PLUGIN_PRIVATE			4
+#define SLAPI_PLUGIN_TYPE			5
+#define SLAPI_PLUGIN_ARGV			6
+#define SLAPI_PLUGIN_ARGC			7
+#define SLAPI_PLUGIN_VERSION			8
+#define SLAPI_PLUGIN_OPRETURN			9
+#define SLAPI_PLUGIN_OBJECT			10
+#define SLAPI_PLUGIN_DESTROY_FN			11
+#define SLAPI_PLUGIN_DESCRIPTION		12
+
+/* internal opreations params */
+#define SLAPI_PLUGIN_INTOP_RESULT		15
+#define SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES	16
+#define SLAPI_PLUGIN_INTOP_SEARCH_REFERRALS	17
+
+/* function pointer params for backends */
+#define SLAPI_PLUGIN_DB_BIND_FN			200
+#define SLAPI_PLUGIN_DB_UNBIND_FN		201
+#define SLAPI_PLUGIN_DB_SEARCH_FN		202
+#define SLAPI_PLUGIN_DB_COMPARE_FN		203
+#define SLAPI_PLUGIN_DB_MODIFY_FN		204
+#define SLAPI_PLUGIN_DB_MODRDN_FN		205
+#define SLAPI_PLUGIN_DB_ADD_FN			206
+#define SLAPI_PLUGIN_DB_DELETE_FN		207
+#define SLAPI_PLUGIN_DB_ABANDON_FN		208
+#define SLAPI_PLUGIN_DB_CONFIG_FN		209
+#define SLAPI_PLUGIN_CLOSE_FN			210
+#define SLAPI_PLUGIN_DB_FLUSH_FN		211
+#define SLAPI_PLUGIN_START_FN			212
+#define SLAPI_PLUGIN_DB_SEQ_FN			213
+#define SLAPI_PLUGIN_DB_ENTRY_FN		214
+#define SLAPI_PLUGIN_DB_REFERRAL_FN		215
+#define SLAPI_PLUGIN_DB_RESULT_FN		216
+#define SLAPI_PLUGIN_DB_LDIF2DB_FN		217
+#define SLAPI_PLUGIN_DB_DB2LDIF_FN		218
+#define SLAPI_PLUGIN_DB_BEGIN_FN		219
+#define SLAPI_PLUGIN_DB_COMMIT_FN		220
+#define SLAPI_PLUGIN_DB_ABORT_FN		221
+#define SLAPI_PLUGIN_DB_ARCHIVE2DB_FN		222
+#define SLAPI_PLUGIN_DB_DB2ARCHIVE_FN		223
+#define SLAPI_PLUGIN_DB_NEXT_SEARCH_ENTRY_FN	224
+#define SLAPI_PLUGIN_DB_FREE_RESULT_SET_FN	225
+#define	SLAPI_PLUGIN_DB_SIZE_FN			226
+#define	SLAPI_PLUGIN_DB_TEST_FN			227
+
+
+/*  functions pointers for LDAP V3 extended ops */
+#define SLAPI_PLUGIN_EXT_OP_FN			300
+#define SLAPI_PLUGIN_EXT_OP_OIDLIST		301
+
+/* functions for preoperation functions */
+#define SLAPI_PLUGIN_PRE_BIND_FN		401
+#define SLAPI_PLUGIN_PRE_UNBIND_FN		402
+#define SLAPI_PLUGIN_PRE_SEARCH_FN		403
+#define SLAPI_PLUGIN_PRE_COMPARE_FN		404
+#define SLAPI_PLUGIN_PRE_MODIFY_FN		405
+#define SLAPI_PLUGIN_PRE_MODRDN_FN		406
+#define SLAPI_PLUGIN_PRE_ADD_FN			407
+#define SLAPI_PLUGIN_PRE_DELETE_FN		408
+#define SLAPI_PLUGIN_PRE_ABANDON_FN		409
+#define SLAPI_PLUGIN_PRE_ENTRY_FN		410
+#define SLAPI_PLUGIN_PRE_REFERRAL_FN		411
+#define SLAPI_PLUGIN_PRE_RESULT_FN		412
+
+/*  functions for postoperation functions*/
+#define SLAPI_PLUGIN_POST_BIND_FN		501
+#define SLAPI_PLUGIN_POST_UNBIND_FN		502
+#define SLAPI_PLUGIN_POST_SEARCH_FN		503
+#define SLAPI_PLUGIN_POST_COMPARE_FN		504
+#define SLAPI_PLUGIN_POST_MODIFY_FN		505
+#define SLAPI_PLUGIN_POST_MODRDN_FN		506
+#define SLAPI_PLUGIN_POST_ADD_FN		507
+#define SLAPI_PLUGIN_POST_DELETE_FN		508
+#define SLAPI_PLUGIN_POST_ABANDON_FN		509
+#define SLAPI_PLUGIN_POST_ENTRY_FN		510
+#define SLAPI_PLUGIN_POST_REFERRAL_FN		511
+#define SLAPI_PLUGIN_POST_RESULT_FN		512
+
+/* audit plugin defines */
+#define SLAPI_PLUGIN_AUDIT_DATA                1100
+#define SLAPI_PLUGIN_AUDIT_FN                  1101
+
+/* managedsait control */
+#define SLAPI_MANAGEDSAIT       		1000
+
+/* config stuff */
+#define SLAPI_CONFIG_FILENAME			40
+#define SLAPI_CONFIG_LINENO			41
+#define SLAPI_CONFIG_ARGC			42
+#define SLAPI_CONFIG_ARGV			43
+
+/*  operational params */
+#define SLAPI_TARGET_DN				50
+#define SLAPI_REQCONTROLS			51
+
+/* server LDAPv3 controls  */
+#define SLAPI_RESCONTROLS			55
+#define SLAPI_ADD_RESCONTROL			56	
+
+/* add params */
+#define SLAPI_ADD_TARGET			SLAPI_TARGET_DN
+#define SLAPI_ADD_ENTRY				60
+
+/* bind params */
+#define SLAPI_BIND_TARGET			SLAPI_TARGET_DN
+#define SLAPI_BIND_METHOD			70
+#define SLAPI_BIND_CREDENTIALS			71	
+#define SLAPI_BIND_SASLMECHANISM		72	
+#define SLAPI_BIND_RET_SASLCREDS		73	
+
+/* compare params */
+#define SLAPI_COMPARE_TARGET			SLAPI_TARGET_DN
+#define SLAPI_COMPARE_TYPE			80
+#define SLAPI_COMPARE_VALUE			81
+
+/* delete params */
+#define SLAPI_DELETE_TARGET			SLAPI_TARGET_DN
+
+/* modify params */
+#define SLAPI_MODIFY_TARGET			SLAPI_TARGET_DN
+#define SLAPI_MODIFY_MODS			90
+
+/* modrdn params */
+#define SLAPI_MODRDN_TARGET			SLAPI_TARGET_DN
+#define SLAPI_MODRDN_NEWRDN			100
+#define SLAPI_MODRDN_DELOLDRDN			101
+#define SLAPI_MODRDN_NEWSUPERIOR		102	/* v3 only */
+
+/* search params */
+#define SLAPI_SEARCH_TARGET			SLAPI_TARGET_DN
+#define SLAPI_SEARCH_SCOPE			110
+#define SLAPI_SEARCH_DEREF			111
+#define SLAPI_SEARCH_SIZELIMIT			112
+#define SLAPI_SEARCH_TIMELIMIT			113
+#define SLAPI_SEARCH_FILTER			114
+#define SLAPI_SEARCH_STRFILTER			115
+#define SLAPI_SEARCH_ATTRS			116
+#define SLAPI_SEARCH_ATTRSONLY			117
+
+/* abandon params */
+#define SLAPI_ABANDON_MSGID			120
+
+/* extended operation params */
+#define SLAPI_EXT_OP_REQ_OID			160
+#define SLAPI_EXT_OP_REQ_VALUE		161	
+
+/* extended operation return codes */
+#define SLAPI_EXT_OP_RET_OID			162	
+#define SLAPI_EXT_OP_RET_VALUE		163	
+
+#define SLAPI_PLUGIN_EXTENDED_SENT_RESULT	-1
+
+/* Search result params */
+#define SLAPI_SEARCH_RESULT_SET			193
+#define	SLAPI_SEARCH_RESULT_ENTRY		194
+#define	SLAPI_NENTRIES				195
+#define SLAPI_SEARCH_REFERRALS			196
+
+
+/* filter types */
+#ifndef LDAP_FILTER_AND
+#define LDAP_FILTER_AND         0xa0L
+#endif
+#ifndef LDAP_FILTER_OR
+#define LDAP_FILTER_OR          0xa1L
+#endif
+#ifndef LDAP_FILTER_NOT
+#define LDAP_FILTER_NOT         0xa2L
+#endif
+#ifndef LDAP_FILTER_EQUALITY
+#define LDAP_FILTER_EQUALITY    0xa3L
+#endif
+#ifndef LDAP_FILTER_SUBSTRINGS
+#define LDAP_FILTER_SUBSTRINGS  0xa4L
+#endif
+#ifndef LDAP_FILTER_GE
+#define LDAP_FILTER_GE          0xa5L
+#endif
+#ifndef LDAP_FILTER_LE
+#define LDAP_FILTER_LE          0xa6L
+#endif
+#ifndef LDAP_FILTER_PRESENT
+#define LDAP_FILTER_PRESENT     0x87L
+#endif
+#ifndef LDAP_FILTER_APPROX
+#define LDAP_FILTER_APPROX      0xa8L
+#endif
+#ifndef LDAP_FILTER_EXT_MATCH
+#define LDAP_FILTER_EXT_MATCH   0xa9L
+#endif
+
+int slapi_log_error( int severity, char *subsystem, char *fmt, ... );
+#define SLAPI_LOG_FATAL                 0
+#define SLAPI_LOG_TRACE                 1
+#define SLAPI_LOG_PACKETS               2
+#define SLAPI_LOG_ARGS                  3
+#define SLAPI_LOG_CONNS                 4
+#define SLAPI_LOG_BER                   5
+#define SLAPI_LOG_FILTER                6
+#define SLAPI_LOG_CONFIG                7
+#define SLAPI_LOG_ACL                   8
+#define SLAPI_LOG_SHELL                 9
+#define SLAPI_LOG_PARSE                 10
+#define SLAPI_LOG_HOUSE                 11
+#define SLAPI_LOG_REPL                  12
+#define SLAPI_LOG_CACHE                 13
+#define SLAPI_LOG_PLUGIN                14
+#define SLAPI_LOG_TIMING                15
+
+#define SLAPI_PLUGIN_DESCRIPTION	12
+typedef struct slapi_plugindesc {
+        char    *spd_id;
+        char    *spd_vendor;
+        char    *spd_version;
+        char    *spd_description;
+} Slapi_PluginDesc;
+
+#define SLAPI_PLUGIN_VERSION_01         "01"
+#define SLAPI_PLUGIN_VERSION_02         "02"
+#define SLAPI_PLUGIN_VERSION_03         "03"
+#define SLAPI_PLUGIN_CURRENT_VERSION    SLAPI_PLUGIN_VERSION_03
+
+#endif /* _SLAPI_PLUGIN_H */
+
diff --git a/servers/slapd/slapi/slapi.h b/servers/slapd/slapi/slapi.h
new file mode 100644
index 0000000000..e46f6c4afb
--- /dev/null
+++ b/servers/slapd/slapi/slapi.h
@@ -0,0 +1,296 @@
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ * (C) Copyright IBM Corp. 1997,2002
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is 
+ * given to IBM Corporation. This software is provided ``as is'' 
+ * without express or implied warranty.
+ */
+
+#ifndef _SLAPI_H
+#define _SLAPI_H
+
+#include <ibm_pblock_params.h> 
+
+typedef struct	slapi_pblock	Slapi_PBlock;
+typedef struct	slap_entry	Slapi_Entry;
+typedef struct	slap_attr	Slapi_Attr;
+typedef Filter			Slapi_Filter;
+
+#include <slapi_utils.h>
+#ifndef NO_PBLOCK_CLASS
+#include <slapi_pblock.h>
+#endif /* NO_PBLOCK_CLASS */
+#include <plugin.h>
+#include <slapi_ops.h>
+#include <slapi_cl.h>
+
+/*
+ * types of plugins
+ */
+#define SLAPI_PLUGIN_DATABASE           1
+#define SLAPI_PLUGIN_EXTENDEDOP         2
+#define SLAPI_PLUGIN_PREOPERATION       3
+#define SLAPI_PLUGIN_POSTOPERATION      4
+#define SLAPI_PLUGIN_MATCHINGRULE       5
+#define SLAPI_PLUGIN_SYNTAX             6
+#define SLAPI_PLUGIN_AUDIT              7
+
+#define SLAPI_PLUGIN_EXTENDED_SENT_RESULT       -1
+#define SLAPI_PLUGIN_EXTENDED_NOT_HANDLED       -2
+
+#define SLAPI_BACKEND				130
+#define SLAPI_CONNECTION			131
+#define SLAPI_OPERATION				132
+#define SLAPI_REQUESTOR_ISROOT			133
+#define SLAPI_BE_MONITORDN			134
+#define SLAPI_BE_TYPE           		135
+#define SLAPI_BE_READONLY       		136
+#define SLAPI_BE_LASTMOD       			137
+#define SLAPI_CONN_ID        			139
+
+#define SLAPI_OPINITIATED_TIME			140
+#define SLAPI_REQUESTOR_DN			141
+#define SLAPI_REQUESTOR_ISUPDATEDN		142
+#define SLAPI_CONN_DN        			143
+#define SLAPI_CONN_AUTHTYPE    			144
+
+#define SLAPD_AUTH_NONE   "none"
+#define SLAPD_AUTH_SIMPLE "simple"
+#define SLAPD_AUTH_SSL    "SSL"
+#define SLAPD_AUTH_SASL   "SASL "
+
+#define SLAPI_PLUGIN				3
+#define SLAPI_PLUGIN_PRIVATE			4
+#define SLAPI_PLUGIN_TYPE			5
+#define SLAPI_PLUGIN_ARGV			6
+#define SLAPI_PLUGIN_ARGC			7
+#define SLAPI_PLUGIN_VERSION			8
+
+#define SLAPI_PLUGIN_OPRETURN			9
+#define SLAPI_PLUGIN_OBJECT			10
+#define SLAPI_PLUGIN_DESTROY_FN			11
+
+#define SLAPI_PLUGIN_DESCRIPTION		12
+
+#define SLAPI_PLUGIN_INTOP_RESULT		15
+#define SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES	16
+#define SLAPI_PLUGIN_INTOP_SEARCH_REFERRALS	17
+
+#define SLAPI_PLUGIN_DB_BIND_FN			200
+#define SLAPI_PLUGIN_DB_UNBIND_FN		201
+#define SLAPI_PLUGIN_DB_SEARCH_FN		202
+#define SLAPI_PLUGIN_DB_COMPARE_FN		203
+#define SLAPI_PLUGIN_DB_MODIFY_FN		204
+#define SLAPI_PLUGIN_DB_MODRDN_FN		205
+#define SLAPI_PLUGIN_DB_ADD_FN			206
+#define SLAPI_PLUGIN_DB_DELETE_FN		207
+#define SLAPI_PLUGIN_DB_ABANDON_FN		208
+#define SLAPI_PLUGIN_DB_CONFIG_FN		209
+#define SLAPI_PLUGIN_CLOSE_FN			210
+#define SLAPI_PLUGIN_DB_FLUSH_FN		211
+#define SLAPI_PLUGIN_START_FN			212
+#define SLAPI_PLUGIN_DB_SEQ_FN			213
+#define SLAPI_PLUGIN_DB_ENTRY_FN		214
+#define SLAPI_PLUGIN_DB_REFERRAL_FN		215
+#define SLAPI_PLUGIN_DB_RESULT_FN		216
+#define SLAPI_PLUGIN_DB_LDIF2DB_FN		217
+#define SLAPI_PLUGIN_DB_DB2LDIF_FN		218
+#define SLAPI_PLUGIN_DB_BEGIN_FN		219
+#define SLAPI_PLUGIN_DB_COMMIT_FN		220
+#define SLAPI_PLUGIN_DB_ABORT_FN		221
+#define SLAPI_PLUGIN_DB_ARCHIVE2DB_FN		222
+#define SLAPI_PLUGIN_DB_DB2ARCHIVE_FN		223
+#define SLAPI_PLUGIN_DB_NEXT_SEARCH_ENTRY_FN	224
+#define SLAPI_PLUGIN_DB_FREE_RESULT_SET_FN	225
+#define	SLAPI_PLUGIN_DB_SIZE_FN			226
+#define	SLAPI_PLUGIN_DB_TEST_FN			227
+#define SLAPI_PLUGIN_DB_NO_ACL        		250
+
+#define SLAPI_PLUGIN_EXT_OP_FN			300
+#define SLAPI_PLUGIN_EXT_OP_OIDLIST		301
+#define SLAPI_PLUGIN_PRE_BIND_FN		401
+#define SLAPI_PLUGIN_PRE_UNBIND_FN		402
+#define SLAPI_PLUGIN_PRE_SEARCH_FN		403
+#define SLAPI_PLUGIN_PRE_COMPARE_FN		404
+#define SLAPI_PLUGIN_PRE_MODIFY_FN		405
+#define SLAPI_PLUGIN_PRE_MODRDN_FN		406
+#define SLAPI_PLUGIN_PRE_ADD_FN			407
+#define SLAPI_PLUGIN_PRE_DELETE_FN		408
+#define SLAPI_PLUGIN_PRE_ABANDON_FN		409
+#define SLAPI_PLUGIN_PRE_ENTRY_FN		410
+#define SLAPI_PLUGIN_PRE_REFERRAL_FN		411
+#define SLAPI_PLUGIN_PRE_RESULT_FN		412
+#define SLAPI_PLUGIN_POST_BIND_FN		501
+#define SLAPI_PLUGIN_POST_UNBIND_FN		502
+#define SLAPI_PLUGIN_POST_SEARCH_FN		503
+#define SLAPI_PLUGIN_POST_COMPARE_FN		504
+#define SLAPI_PLUGIN_POST_MODIFY_FN		505
+#define SLAPI_PLUGIN_POST_MODRDN_FN		506
+#define SLAPI_PLUGIN_POST_ADD_FN		507
+#define SLAPI_PLUGIN_POST_DELETE_FN		508
+#define SLAPI_PLUGIN_POST_ABANDON_FN		509
+#define SLAPI_PLUGIN_POST_ENTRY_FN		510
+#define SLAPI_PLUGIN_POST_REFERRAL_FN		511
+#define SLAPI_PLUGIN_POST_RESULT_FN		512
+
+#define SLAPI_PLUGIN_MR_FILTER_CREATE_FN	600
+#define SLAPI_PLUGIN_MR_INDEXER_CREATE_FN	601
+#define SLAPI_PLUGIN_MR_FILTER_MATCH_FN		602
+#define SLAPI_PLUGIN_MR_FILTER_INDEX_FN		603
+#define SLAPI_PLUGIN_MR_FILTER_RESET_FN		604
+#define SLAPI_PLUGIN_MR_INDEX_FN		605
+#define SLAPI_PLUGIN_MR_OID			610
+#define SLAPI_PLUGIN_MR_TYPE			611
+#define SLAPI_PLUGIN_MR_VALUE			612
+#define SLAPI_PLUGIN_MR_VALUES			613
+#define SLAPI_PLUGIN_MR_KEYS			614
+#define SLAPI_PLUGIN_MR_FILTER_REUSABLE		615
+#define SLAPI_PLUGIN_MR_QUERY_OPERATOR		616
+#define SLAPI_PLUGIN_MR_USAGE			617
+
+#define SLAPI_OP_LESS					1
+#define SLAPI_OP_LESS_OR_EQUAL				2
+#define SLAPI_OP_EQUAL					3
+#define SLAPI_OP_GREATER_OR_EQUAL			4
+#define SLAPI_OP_GREATER				5
+#define SLAPI_OP_SUBSTRING				6
+
+#define SLAPI_PLUGIN_MR_USAGE_INDEX		0
+#define SLAPI_PLUGIN_MR_USAGE_SORT		1
+
+#define SLAPI_PLUGIN_SYNTAX_FILTER_AVA		700
+#define SLAPI_PLUGIN_SYNTAX_FILTER_SUB		701
+#define SLAPI_PLUGIN_SYNTAX_VALUES2KEYS		702
+#define SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_AVA	703
+#define SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_SUB	704
+#define SLAPI_PLUGIN_SYNTAX_NAMES		705
+#define SLAPI_PLUGIN_SYNTAX_OID			706
+#define SLAPI_PLUGIN_SYNTAX_FLAGS		707
+#define SLAPI_PLUGIN_SYNTAX_COMPARE		708
+
+#define SLAPI_PLUGIN_SYNTAX_FLAG_ORKEYS			1
+#define SLAPI_PLUGIN_SYNTAX_FLAG_ORDERING		2
+
+#define SLAPI_PLUGIN_AUDIT_DATA                 1100
+#define SLAPI_PLUGIN_AUDIT_FN                   1101
+
+#define SLAPI_MANAGEDSAIT       		1000
+
+#define SLAPI_CONFIG_FILENAME			40
+#define SLAPI_CONFIG_LINENO			41
+#define SLAPI_CONFIG_ARGC			42
+#define SLAPI_CONFIG_ARGV			43
+
+#define SLAPI_TARGET_DN				50
+#define SLAPI_REQCONTROLS			51
+
+#define	SLAPI_ENTRY_PRE_OP			52
+#define	SLAPI_ENTRY_POST_OP			53
+
+#define SLAPI_RESCONTROLS			55
+#define SLAPI_ADD_RESCONTROL			56
+
+#define SLAPI_ADD_TARGET			SLAPI_TARGET_DN
+#define SLAPI_ADD_ENTRY				60
+
+#define SLAPI_BIND_TARGET			SLAPI_TARGET_DN
+#define SLAPI_BIND_METHOD			70
+#define SLAPI_BIND_CREDENTIALS			71
+#define SLAPI_BIND_SASLMECHANISM		72
+#define SLAPI_BIND_RET_SASLCREDS		73
+
+#define SLAPI_COMPARE_TARGET			SLAPI_TARGET_DN
+#define SLAPI_COMPARE_TYPE			80
+#define SLAPI_COMPARE_VALUE			81
+
+#define SLAPI_DELETE_TARGET			SLAPI_TARGET_DN
+
+#define SLAPI_MODIFY_TARGET			SLAPI_TARGET_DN
+#define SLAPI_MODIFY_MODS			90
+
+#define SLAPI_MODRDN_TARGET			SLAPI_TARGET_DN
+#define SLAPI_MODRDN_NEWRDN			100
+#define SLAPI_MODRDN_DELOLDRDN			101
+#define SLAPI_MODRDN_NEWSUPERIOR		102
+
+#define SLAPI_SEARCH_TARGET			SLAPI_TARGET_DN
+#define SLAPI_SEARCH_SCOPE			110
+#define SLAPI_SEARCH_DEREF			111
+#define SLAPI_SEARCH_SIZELIMIT			112
+#define SLAPI_SEARCH_TIMELIMIT			113
+#define SLAPI_SEARCH_FILTER			114
+#define SLAPI_SEARCH_STRFILTER			115
+#define SLAPI_SEARCH_ATTRS			116
+#define SLAPI_SEARCH_ATTRSONLY			117
+
+#define SLAPI_ABANDON_MSGID			120
+
+#define SLAPI_SEQ_TYPE				150
+#define SLAPI_SEQ_ATTRNAME			151
+#define SLAPI_SEQ_VAL				152
+
+#define SLAPI_EXT_OP_REQ_OID			160
+#define SLAPI_EXT_OP_REQ_VALUE			161
+#define SLAPI_EXT_OP_RET_OID			162
+#define SLAPI_EXT_OP_RET_VALUE			163
+
+#define SLAPI_MR_FILTER_ENTRY			170	
+#define SLAPI_MR_FILTER_TYPE			171
+#define SLAPI_MR_FILTER_VALUE			172
+#define SLAPI_MR_FILTER_OID			173
+#define SLAPI_MR_FILTER_DNATTRS			174
+
+#define SLAPI_LDIF2DB_FILE			180
+#define SLAPI_LDIF2DB_REMOVEDUPVALS		185
+
+#define SLAPI_DB2LDIF_PRINTKEY			183
+
+#define SLAPI_PARENT_TXN			190
+#define SLAPI_TXN				191
+
+#define SLAPI_SEARCH_RESULT_SET			193
+#define	SLAPI_SEARCH_RESULT_ENTRY		194
+#define	SLAPI_NENTRIES				195
+#define SLAPI_SEARCH_REFERRALS			196
+
+#define	SLAPI_CHANGENUMBER			197
+#define	SLAPI_LOG_OPERATION			198
+
+#define SLAPI_DBSIZE				199
+
+#define SLAPI_LOG_FATAL          		0
+#define SLAPI_LOG_TRACE				1
+#define SLAPI_LOG_PACKETS			2
+#define SLAPI_LOG_ARGS				3
+#define SLAPI_LOG_CONNS				4
+#define SLAPI_LOG_BER				5
+#define SLAPI_LOG_FILTER			6
+#define SLAPI_LOG_CONFIG			7
+#define SLAPI_LOG_ACL				8
+#define SLAPI_LOG_SHELL				9
+#define SLAPI_LOG_PARSE				10
+#define SLAPI_LOG_HOUSE				11
+#define SLAPI_LOG_REPL				12
+#define SLAPI_LOG_CACHE				13
+#define SLAPI_LOG_PLUGIN			14
+
+#define SLAPI_OPERATION_BIND            	0x00000001L
+#define SLAPI_OPERATION_UNBIND          	0x00000002L
+#define SLAPI_OPERATION_SEARCH          	0x00000004L
+#define SLAPI_OPERATION_MODIFY          	0x00000008L
+#define SLAPI_OPERATION_ADD             	0x00000010L
+#define SLAPI_OPERATION_DELETE          	0x00000020L
+#define SLAPI_OPERATION_MODDN           	0x00000040L
+#define SLAPI_OPERATION_MODRDN          	SLAPI_OPERATION_MODDN
+#define SLAPI_OPERATION_COMPARE         	0x00000080L
+#define SLAPI_OPERATION_ABANDON         	0x00000100L
+#define SLAPI_OPERATION_EXTENDED        	0x00000200L
+#define SLAPI_OPERATION_ANY             	0xFFFFFFFFL
+#define SLAPI_OPERATION_NONE            	0x00000000L
+
+#endif /* _SLAPI_H */
+
diff --git a/servers/slapd/slapi/slapi_cl.h b/servers/slapd/slapi/slapi_cl.h
new file mode 100644
index 0000000000..ad4ac6eb67
--- /dev/null
+++ b/servers/slapd/slapi/slapi_cl.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ * (C) Copyright IBM Corp. 1997,2002
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is 
+ * given to IBM Corporation. This software is provided ``as is'' 
+ * without express or implied warranty.
+ */
+
+#ifndef _SLAPI_CL_H
+#define _SLAPI_CL_H
+
+#define TIME_SIZE 20
+#define OBJECTCLASS "objectclass"
+#define TOP "top"
+#define CHANGE_TIME "changetime"
+#define CHANGE_TYPE "changetype"
+#define CHANGE_TARGETDN "targetdn"
+#define CHANGES	"changes"
+#define CHANGE_NUMBER "changenumber"
+/*
+ * FIXME: I get complaints like "ADD" being redefined - first definition
+ * being in "/usr/include/arpa/nameser.h:552"
+ */
+#undef ADD
+#define ADD "add: "
+#define ADDLEN 5
+#define DEL "delete: "
+#define DELLEN 8
+#define REPLACE "replace: "
+#define REPLEN 9
+#define MOD "modify"
+#define MODRDN "modrdn"
+#define CHANGE_LOGENTRY "changelogentry"
+#define IBM_CHANGE_LOGENTRY "ibm-changelog"
+#define CL_NEWRDN "newrdn"
+#define CL_DELRDN "deleteoldrdn"
+#define CHANGE_INITIATOR "ibm-changeInitiatorsName" 
+
+void slapi_register_changelog_suffix(char *suffix);
+char **slapi_get_changelog_suffixes();
+void slapi_update_changelog_counters(long curNum, long numEntries);
+char *slapi_get_cl_firstNum();
+char *slapi_get_cl_lastNum();
+int slapi_add_to_changelog(Slapi_Entry *ent, char *suffix, char *chNum, Operation* op);	
+int slapi_delete_changelog(char *dn, char *suffix, char *chNum, Operation* op);	
+int slapi_modify_changelog(char *dn,LDAPMod	*mods,char *suffix, char *chNum, Operation* op); 
+int slapi_modifyrdn_changelog(char *olddn, char *newRdn, int delRdn, char *suffix, char *chNum, Operation* op);
+Backend * slapi_cl_get_be(char *dn);
+
+#endif /* _SLAPI_CL_H */
+
diff --git a/servers/slapd/slapi/slapi_common.h b/servers/slapd/slapi/slapi_common.h
new file mode 100644
index 0000000000..7a97d5d403
--- /dev/null
+++ b/servers/slapd/slapi/slapi_common.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ * (C) Copyright IBM Corp. 1997,2002
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is 
+ * given to IBM Corporation. This software is provided ``as is'' 
+ * without express or implied warranty.
+ */
+
+#ifndef SLAPI_COMMON_H
+#define SLAPI_COMMON_H
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define dn_normalize_case	dn_normalize
+#define SLAPD_NO_MEMORY    	7
+#define ANYBODY_STRING 		"CN=ANYBODY"
+
+extern int slap_debug;
+
+int
+dn_check(char *, int  *);
+
+
+typedef struct strlist {
+	char *string;
+	struct strlist *next;
+} StrList;
+
+#endif /* SLAPI_COMMON_H */
+
diff --git a/servers/slapd/slapi/slapi_ops.c b/servers/slapd/slapi/slapi_ops.c
new file mode 100644
index 0000000000..4ff9264c42
--- /dev/null
+++ b/servers/slapd/slapi/slapi_ops.c
@@ -0,0 +1,1269 @@
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ * (C) Copyright IBM Corp. 1997,2002
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is
+ * given to IBM Corporation. This software is provided ``as is''
+ * without express or implied warranty.
+ */
+
+#include "portable.h"
+#include "slapi_common.h"
+#include <slap.h>
+#include <slapi.h>
+#include <lber.h>
+#include "../../../libraries/liblber/lber-int.h"
+
+
+int bvptr2obj( struct berval **bvptr, struct berval **bvobj );
+
+int
+internal_result_v3(
+	Connection *conn, 
+	Operation *op, 
+	int err,
+	char *matched, 
+	char *text, 
+	char **referrals )
+{
+	return LDAP_SUCCESS;
+}
+
+int
+internal_search_entry(
+	Backend *be, 
+	Connection *conn, 
+	Operation *op, 
+	Entry *e, 
+	char **attrs, 
+	int attrsonly, 
+	char **denied_attrs ) 
+{
+	char *ent2str = NULL;
+	int nentries = 0, len = 0, i = 0;
+	Slapi_Entry **head = NULL, **tp;
+	
+	ent2str = slapi_entry2str( e, &len );
+	if ( ent2str == NULL ) {
+		return SLAPD_NO_MEMORY;
+	}
+
+	slapi_pblock_get( (Slapi_PBlock *)op->o_pb,
+			SLAPI_NENTRIES, &nentries );
+	slapi_pblock_get( (Slapi_PBlock *)op->o_pb,
+			SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &head );
+	
+	i = nentries + 1;
+	if ( nentries == 0 ) {
+		tp = (Slapi_Entry **)slapi_ch_malloc( 2 * sizeof(Slapi_Entry *) );
+		if ( tp == NULL ) {
+			return SLAPD_NO_MEMORY;
+		}
+
+		tp[ 0 ] = (Slapi_Entry *)str2entry( ent2str );
+		if ( tp[ 0 ] == NULL ) { 
+			return SLAPD_NO_MEMORY;
+		}
+
+	} else {
+		tp = (Slapi_Entry **)slapi_ch_realloc( (char *)head,
+				sizeof(Slapi_Entry *) * ( i + 1 ) );
+		if ( tp == NULL ) {
+			return SLAPD_NO_MEMORY;
+		}
+		tp[ i - 1 ] = (Slapi_Entry *)str2entry( ent2str );
+		if ( tp[ i - 1 ] == NULL ) { 
+			return SLAPD_NO_MEMORY;
+		}
+	}
+	tp[ i ] = NULL;
+	          
+	slapi_pblock_set( (Slapi_PBlock *)op->o_pb,
+			SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, (void *)tp );
+	slapi_pblock_set( (Slapi_PBlock *)op->o_pb,
+			SLAPI_NENTRIES, (void *)i );
+	slapi_ch_free( ent2str );
+
+	return LDAP_SUCCESS;
+}
+
+int
+internal_search_result(
+	Connection *conn, 
+	Operation *op,
+	int err, 
+	char *matched, 
+	char *text, 
+	int nentries ) 
+{
+	slapi_pblock_set( (Slapi_PBlock *)op->o_pb,
+			SLAPI_NENTRIES, (void *)nentries );
+
+	return LDAP_SUCCESS;
+}
+
+int
+internal_result_ext(
+	Connection *conn, 
+	Operation *op, 
+	int  errnum, 
+	char *respname, 
+	struct berval *response )
+{
+	return LDAP_SUCCESS;
+}
+
+int
+internal_search_reference(
+	Connection *conn, 
+	Operation *op, 
+	char **ref ) 
+{
+	return LDAP_SUCCESS;
+}
+
+static Connection *
+fakeConnection(
+	char *DN, 
+	int OpType ) 
+{ 
+	Connection *pConn, *c;
+	ber_len_t max = sockbuf_max_incoming;
+
+	pConn = (Connection *) slapi_ch_calloc(1, sizeof(Connection));
+	if (pConn == NULL) {
+		return (Connection *)NULL;
+	}
+
+	LDAP_STAILQ_INIT( &pConn->c_pending_ops );
+
+	pConn->c_pending_ops.stqh_first =
+		(Operation *) slapi_ch_calloc( 1, sizeof(Operation) );
+	if ( pConn->c_pending_ops.stqh_first == NULL ) { 
+		slapi_ch_free( pConn );
+		return (Connection *)NULL;
+	}
+
+	pConn->c_pending_ops.stqh_first->o_pb = 
+		(Slapi_PBlock *) slapi_pblock_new();
+	if ( pConn->c_pending_ops.stqh_first->o_pb == NULL ) {
+		slapi_ch_free( pConn->c_pending_ops.stqh_first );
+		slapi_ch_free( pConn );
+		return (Connection *)NULL;
+	}
+
+	c = pConn;
+
+	/* operation object */
+	c->c_pending_ops.stqh_first->o_tag = OpType;
+	c->c_pending_ops.stqh_first->o_protocol = LDAP_VERSION3; 
+	c->c_pending_ops.stqh_first->o_authmech.bv_val = NULL; 
+	c->c_pending_ops.stqh_first->o_authmech.bv_len = 0; 
+	c->c_pending_ops.stqh_first->o_time = slap_get_time();
+
+	/* connection object */
+	c->c_authmech.bv_val = NULL;
+	c->c_authmech.bv_len = 0;
+	c->c_dn.bv_val = NULL;
+	c->c_dn.bv_len = 0;
+	c->c_ndn.bv_val = NULL;
+	c->c_ndn.bv_len = 0;
+	c->c_groups = NULL;
+
+	c->c_listener = NULL;
+	c->c_peer_domain.bv_val = NULL;
+	c->c_peer_domain.bv_len = 0;
+	c->c_peer_name.bv_val = NULL;
+	c->c_peer_name.bv_len = 0;
+
+	LDAP_STAILQ_INIT( &c->c_ops );
+
+	c->c_sasl_bind_mech.bv_val = NULL;
+	c->c_sasl_bind_mech.bv_len = 0;
+	c->c_sasl_context = NULL;
+	c->c_sasl_extra = NULL;
+
+	c->c_sb = ber_sockbuf_alloc( );
+
+	ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max );
+
+	c->c_currentber = NULL;
+
+	/* should check status of thread calls */
+	ldap_pvt_thread_mutex_init( &c->c_mutex );
+	ldap_pvt_thread_mutex_init( &c->c_write_mutex );
+	ldap_pvt_thread_cond_init( &c->c_write_cv );
+
+	c->c_n_ops_received = 0;
+	c->c_n_ops_executing = 0;
+	c->c_n_ops_pending = 0;
+	c->c_n_ops_completed = 0;
+
+	c->c_n_get = 0;
+	c->c_n_read = 0;
+	c->c_n_write = 0;
+
+	c->c_protocol = LDAP_VERSION3; 
+
+	c->c_activitytime = c->c_starttime = slap_get_time();
+
+	c->c_connid = 0;
+
+	c->c_conn_state  = 0x01;	/* SLAP_C_ACTIVE */
+	c->c_struct_state = 0x02;	/* SLAP_C_USED */
+
+	c->c_ssf = c->c_transport_ssf = 0;
+	c->c_tls_ssf = 0;
+
+	backend_connection_init( c );
+
+	pConn->c_send_ldap_result =
+		(SEND_LDAP_RESULT) internal_result_v3;
+	pConn->c_send_search_entry =
+		(SEND_SEARCH_ENTRY) internal_search_entry;
+	pConn->c_send_search_result =
+		(SEND_SEARCH_RESULT) internal_search_result;
+	pConn->c_send_ldap_extended =
+		(SEND_LDAP_EXTENDED) internal_result_ext;
+	pConn->c_send_search_reference =
+		(SEND_SEARCH_REFERENCE) internal_search_reference;
+
+	return pConn;
+}
+
+/* 
+ * Function : ValuestoBValues 
+ * Convert an array of char ptrs to an array of berval ptrs.
+ * return value : LDAP_SUCCESS
+ *                LDAP_NO_MEMORY
+ *                LDAP_OTHER
+*/
+
+static int 
+ValuesToBValues(
+	char **ppValue, 
+	struct berval ***pppBV )
+{
+	int  rc = LDAP_SUCCESS;
+	int  i;
+	struct berval *pTmpBV;
+	struct berval **ppNewBV;
+
+	/* count the number of char ptrs. */
+	for ( i = 0; ppValue != NULL && ppValue[i] != NULL; i++ ) {
+		;	/* NULL */
+	}
+
+	if ( i == 0 ) {
+		rc = LDAP_OTHER;
+	} else {
+		*pppBV = ppNewBV = (struct berval **)slapi_ch_malloc( (i+1)*(sizeof(struct berval *)) );
+		if ( *pppBV == NULL ) {
+			rc = LDAP_NO_MEMORY;
+		} else {
+			while ( ppValue != NULL && *ppValue != NULL && rc == LDAP_SUCCESS ) {
+				pTmpBV = (struct berval *)slapi_ch_malloc(sizeof(struct berval));
+				if ( pTmpBV == NULL) {
+					rc = LDAP_NO_MEMORY;
+				} else {
+					pTmpBV->bv_val = slapi_ch_strdup(*ppValue);
+					if ( pTmpBV->bv_val == NULL ) {
+						rc = LDAP_NO_MEMORY;
+					} else {
+						pTmpBV->bv_len = strlen(*ppValue);
+						*ppNewBV = pTmpBV;
+						ppNewBV++;
+					}
+					ppValue++;
+				}
+			}
+			/* null terminate the array of berval ptrs */
+			*ppNewBV = NULL;
+		}
+	}
+	return( rc );
+}
+
+
+/*
+ * Function : LDAPModToEntry 
+ * convert a dn plus an array of LDAPMod struct ptrs to an entry structure
+ * with a link list of the correspondent attributes.
+ * Return value : LDAP_SUCCESS
+ *                LDAP_NO_MEMORY
+ *                LDAP_OTHER
+*/
+Entry *
+LDAPModToEntry(
+	char *ldn, 
+	LDAPMod **mods )
+{
+	struct berval		dn = { 0, NULL };
+	Entry			*pEntry=NULL;
+	LDAPMod			*pMod;
+	struct berval		*bv;
+	struct berval		**ppBV;
+	Backend			*be;
+	Operation		*op;
+
+	Modifications		*modlist = NULL;
+	Modifications		**modtail = &modlist;
+	Modifications		tmp;
+
+	int			rc = LDAP_SUCCESS;
+	int			i;
+
+	const char 		*text = NULL;
+
+
+	op = (Operation *) slapi_ch_calloc(1, sizeof(Operation));
+	if ( pEntry == NULL) {
+		rc = LDAP_NO_MEMORY;
+		goto cleanup;
+	}  
+	op->o_tag = LDAP_REQ_ADD;
+
+	pEntry = (Entry *) ch_calloc( 1, sizeof(Entry) );
+	if ( pEntry == NULL) {
+		rc = LDAP_NO_MEMORY;
+		goto cleanup;
+	} 
+
+	dn.bv_val = slapi_ch_strdup(ldn);
+	dn.bv_len = strlen(ldn);
+
+	rc = dnPrettyNormal( NULL, &dn, &pEntry->e_name, &pEntry->e_nname );
+	if (rc != LDAP_SUCCESS) goto cleanup;
+
+	if ( rc == LDAP_SUCCESS ) {
+		for ( i=0, pMod=mods[0]; rc == LDAP_SUCCESS && pMod != NULL; pMod=mods[++i]) {
+			Modifications *mod;
+			if ( (pMod->mod_op & LDAP_MOD_BVALUES) != 0 ) {
+				/* attr values are in berval format */
+				/* convert an array of pointers to bervals to an array of bervals */
+				rc = bvptr2obj(pMod->mod_bvalues, &bv);
+				if (rc != LDAP_SUCCESS) goto cleanup;
+				tmp.sml_type.bv_val = slapi_ch_strdup(pMod->mod_type);
+				tmp.sml_type.bv_len = slapi_ch_stlen(pMod->mod_type);
+				tmp.sml_bvalues = bv;
+		
+				mod  = (Modifications *) ch_malloc( sizeof(Modifications) );
+
+				mod->sml_op = LDAP_MOD_ADD;
+				mod->sml_next = NULL;
+				mod->sml_desc = NULL;
+				mod->sml_type = tmp.sml_type;
+				mod->sml_bvalues = tmp.sml_bvalues;
+
+				*modtail = mod;
+				modtail = &mod->sml_next;
+
+			} else {
+				/* attr values are in string format, need to be converted */
+				/* to an array of bervals */ 
+				if ( pMod->mod_values == NULL ) {
+					rc = LDAP_OTHER;
+				} else {
+					rc = ValuesToBValues( pMod->mod_values, &ppBV );
+					if (rc != LDAP_SUCCESS) goto cleanup;
+					rc = bvptr2obj(ppBV, &bv);
+					if (rc != LDAP_SUCCESS) goto cleanup;
+					tmp.sml_type.bv_val = slapi_ch_strdup(pMod->mod_type);
+					tmp.sml_type.bv_len = slapi_ch_stlen(pMod->mod_type);
+					tmp.sml_bvalues = bv;
+		
+					mod  = (Modifications *) ch_malloc( sizeof(Modifications) );
+
+					mod->sml_op = LDAP_MOD_ADD;
+					mod->sml_next = NULL;
+					mod->sml_desc = NULL;
+					mod->sml_type = tmp.sml_type;
+					mod->sml_bvalues = tmp.sml_bvalues;
+
+					*modtail = mod;
+					modtail = &mod->sml_next;
+
+					if ( ppBV != NULL ) {
+						ber_bvecfree( ppBV );
+					}
+				}
+			}
+		} /* for each LDAPMod */
+	}
+
+	be = select_backend(&dn, 0, 0);
+	if ( be == NULL ) {
+		rc =  LDAP_PARTIAL_RESULTS;
+		goto cleanup;
+	}
+
+	if ( be ) {
+		int repl_user = be_isupdate(be, &be->be_rootdn );
+        	if ( !be->be_update_ndn.bv_len || repl_user ) {
+			int update = be->be_update_ndn.bv_len;
+			char textbuf[SLAP_TEXT_BUFLEN];
+			size_t textlen = sizeof textbuf;
+
+			rc = slap_mods_check( modlist, update, &text, 
+					textbuf, textlen );
+			if ( rc != LDAP_SUCCESS) {
+				goto cleanup;
+			}
+
+			if ( !repl_user ) {
+				rc = slap_mods_opattrs( be, op,
+						modlist, modtail, &text, 
+						textbuf, textlen );
+				if ( rc != LDAP_SUCCESS) {
+					goto cleanup;
+				}
+			}
+
+			/*
+			 * FIXME: slap_mods2entry is declared static 
+			 * in servers/slapd/add.c
+			 */
+			rc = slap_mods2entry( modlist, &pEntry, repl_user,
+					&text, textbuf, textlen );
+			if (rc != LDAP_SUCCESS) {
+				goto cleanup;
+			}
+
+		} else {
+			rc = LDAP_REFERRAL;
+		}
+	} else {
+		rc = LDAP_UNWILLING_TO_PERFORM;
+	}
+
+cleanup:
+
+	if ( dn.bv_val ) slapi_ch_free( dn.bv_val );
+	if ( op ) slapi_ch_free( op );
+	if ( modlist != NULL ) slap_mods_free( modlist );
+	if ( rc != LDAP_SUCCESS ) {
+		if ( pEntry != NULL ) {
+			slapi_entry_free( pEntry );
+		}
+		pEntry = NULL;
+	}
+
+	return( pEntry );
+}
+
+/* Function : slapi_delete_internal
+ *
+ * Description : Plugin functions call this routine to delete an entry 
+ *               in the backend directly
+ * Return values : LDAP_SUCCESS
+ *                 LDAP_OPERAITONS_ERROR
+ *                 LDAP_NO_MEMORY
+ *                 LDAP_OTHER
+ *                 LDAP_UNWILLING_TO_PERFORM
+*/
+Slapi_PBlock *
+slapi_delete_internal(
+	char *ldn, 
+	LDAPControl **controls, 
+	int log_change )
+{
+#if defined(LDAP_SLAPI)
+	Backend			*be;
+	Connection		*pConn = NULL;
+	Operation		*op = NULL;
+	Slapi_PBlock		*pPB = NULL;
+	Slapi_PBlock		*pSavePB = NULL;
+
+	struct berval dn  = { 0, NULL };
+	struct berval pdn = { 0, NULL };
+	struct berval ndn = { 0, NULL };
+
+	int				rc=LDAP_SUCCESS;
+	int				manageDsaIt = 0;
+	int				isCritical;
+
+	if ( ldn == NULL ) {
+		rc = LDAP_OPERATIONS_ERROR; 
+		goto cleanup;
+	}
+
+	pConn = fakeConnection( NULL,  LDAP_REQ_DELETE );
+	if (pConn == NULL) {
+		rc = LDAP_NO_MEMORY;
+		goto cleanup;
+	}
+
+	op = (Operation *)pConn->c_pending_ops.stqh_first;
+	pPB = (Slapi_PBlock *)op->o_pb;
+	op->o_ctrls = controls;
+
+	dn.bv_val = slapi_ch_strdup(ldn);
+	dn.bv_len = slapi_strlen(ldn);
+	rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn );
+	if ( rc != LDAP_SUCCESS ) goto cleanup;
+
+	if ( slapi_control_present( controls, 
+			SLAPI_CONTROL_MANAGEDSAIT_OID, NULL, &isCritical) ) {
+		manageDsaIt = 1; 
+	}
+
+	be = select_backend( &dn, manageDsaIt, 0 );
+	if ( be == NULL ) {
+		rc =  LDAP_PARTIAL_RESULTS;
+		goto cleanup;
+	}
+
+	op->o_ndn.bv_val = slapi_ch_strdup(be->be_rootdn.bv_val);
+	op->o_ndn.bv_len = be->be_rootdn.bv_len;
+	pConn->c_dn.bv_val = slapi_ch_strdup(be->be_rootdn.bv_val);
+	pConn->c_dn.bv_len = be->be_rootdn.bv_len;
+
+	suffix_alias( be, &ndn );
+
+	if ( be->be_delete ) {
+		int repl_user = be_isupdate( be, &op->o_ndn );
+		if ( !be->be_update_ndn.bv_len || repl_user ) {
+			rc = (*be->be_delete)( be, pConn, op, &pdn, &ndn );
+			if ( rc == 0 ) {
+				if (log_change) {
+					replog( be, op, &pdn, &ndn, NULL );
+				}
+				rc = LDAP_SUCCESS;
+			} else {
+				rc = LDAP_OPERATIONS_ERROR;
+			}
+        	} else {
+			rc = LDAP_REFERRAL;
+        	}
+	} else {
+		rc = LDAP_UNWILLING_TO_PERFORM;
+	}
+
+cleanup:
+	if (pPB != NULL) 
+		slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
+
+	if (dn.bv_val) slapi_ch_free(dn.bv_val);
+	if (pdn.bv_val) slapi_ch_free(pdn.bv_val);
+	if (ndn.bv_val) slapi_ch_free(ndn.bv_val);
+
+	if ( pConn != NULL ) {
+		if ( pConn->c_dn.bv_val ) slapi_ch_free( pConn->c_dn.bv_val );
+		if ( op->o_dn.bv_val ) slapi_ch_free( op->o_dn.bv_val );
+		if ( op ) slapi_ch_free( op );
+		pSavePB = pPB;
+		free( pConn );
+	}
+	
+	return (pSavePB);
+#endif /* LDAP_SLAPI */
+	return NULL;
+}
+
+Slapi_PBlock * 
+slapi_add_entry_internal(
+	Slapi_Entry *e, 
+	LDAPControl **controls, 
+	int log_changes ) 
+{
+#if defined(LDAP_SLAPI)
+	Connection		*pConn = NULL;
+	Operation		*op = NULL;
+	Slapi_PBlock		*pPB = NULL, *pSavePB = NULL;
+	Backend			*be;
+
+	int			manageDsaIt = 0;
+	int			isCritical;
+	int			rc = LDAP_SUCCESS;
+
+	if ( e == NULL ) {
+		rc = LDAP_OPERATIONS_ERROR;
+		goto cleanup;
+	}
+	
+	pConn = fakeConnection( NULL, LDAP_REQ_ADD );
+	if ( pConn == NULL ) {
+		rc = LDAP_NO_MEMORY;
+		goto cleanup;
+	}
+
+	if ( slapi_control_present( controls, LDAP_CONTROL_MANAGEDSAIT,
+				NULL, &isCritical ) ) {
+		manageDsaIt = 1; 
+	}
+
+	op = (Operation *)pConn->c_pending_ops.stqh_first;
+	pPB = (Slapi_PBlock *)op->o_pb;
+	op->o_ctrls = controls;
+
+	be = select_backend( &e->e_nname, manageDsaIt, 0 );
+	if ( be == NULL ) {
+		rc = LDAP_PARTIAL_RESULTS;
+		goto cleanup;
+	}
+
+	op->o_ndn.bv_val = slapi_ch_strdup( be->be_rootdn.bv_val );
+	op->o_ndn.bv_len = be->be_rootdn.bv_len;
+	pConn->c_dn.bv_val = slapi_ch_strdup( be->be_rootdn.bv_val );
+	pConn->c_dn.bv_len = be->be_rootdn.bv_len;
+
+	if ( be->be_add ) {
+		int repl_user = be_isupdate( be, &op->o_ndn );
+		if ( !be->be_update_ndn.bv_len || repl_user ){
+			if ( (*be->be_add)( be, pConn, op, e ) == 0 ) {
+				if ( log_changes ) {
+					replog( be, op, &e->e_name, 
+							&e->e_nname, e );
+				}
+				rc = LDAP_SUCCESS;
+			}
+		} else {
+			rc = LDAP_REFERRAL;
+		}
+	} else {
+		rc = LDAP_UNWILLING_TO_PERFORM;
+	}
+
+cleanup:
+
+	if ( pPB != NULL ) {
+		slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
+	}
+
+	if ( pConn != NULL ) {
+		if ( pConn->c_dn.bv_val ) slapi_ch_free( pConn->c_dn.bv_val );
+		if ( op ) {
+			if ( op->o_ndn.bv_val ) {
+				slapi_ch_free( op->o_ndn.bv_val );
+			}
+			free(op);
+		}
+		pSavePB = pPB;
+		free( pConn );
+	}
+	return( pSavePB );
+#endif /* LDAP_SLAPI */
+	return NULL;
+}
+
+
+Slapi_PBlock *
+slapi_add_internal(
+	char *dn, 
+	LDAPMod **mods, 
+	LDAPControl **controls, 
+	int log_changes  ) 
+{
+#if defined(LDAP_SLAPI)
+	LDAPMod			*pMod = NULL;
+	Slapi_PBlock		*pb = NULL;
+	Entry			*pEntry = NULL;
+	int			i, rc=LDAP_SUCCESS;
+
+	if ( mods == NULL || *mods == NULL || dn == NULL || *dn == '\0' ) {
+		rc = LDAP_OPERATIONS_ERROR ;
+	}
+
+	if ( rc == LDAP_SUCCESS ) {
+		for ( i = 0, pMod = mods[0]; pMod != NULL; pMod = mods[++i] ) {
+			if ( (pMod->mod_op & ~LDAP_MOD_BVALUES) != LDAP_MOD_ADD ) {
+				rc = LDAP_OTHER;
+				break;
+			}
+		}
+	}
+
+	if ( rc == LDAP_SUCCESS ) {
+		if((pEntry = LDAPModToEntry( dn, mods )) == NULL) {
+			rc = LDAP_OTHER;
+		}
+	}
+
+	if ( rc != LDAP_SUCCESS ) {
+		pb = slapi_pblock_new();
+		slapi_pblock_set( pb, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
+	} else {
+		pb = slapi_add_entry_internal( pEntry, controls, log_changes );
+	}
+
+	if ( pEntry ) {
+		slapi_entry_free(pEntry);
+	}
+
+	return(pb);
+#endif /* LDAP_SLAPI */
+	return NULL;
+}
+
+/* Function : slapi_modrdn_internal
+ *
+ * Description : Plugin functions call this routine to modify the rdn 
+ *				 of an entry in the backend directly
+ * Return values : LDAP_SUCCESS
+ *                 LDAP_OPERAITONS_ERROR
+ *                 LDAP_NO_MEMORY
+ *                 LDAP_OTHER
+ *                 LDAP_UNWILLING_TO_PERFORM
+ *
+ * NOTE: This function does not support the "newSuperior" option from LDAP V3.
+ */
+Slapi_PBlock *
+slapi_modrdn_internal(
+	char *olddn, 
+	char *lnewrdn, 
+	int deloldrdn, 
+	LDAPControl **controls, 
+	int log_change )
+{
+#if defined(LDAP_SLAPI)
+	int			rc = LDAP_SUCCESS;
+
+	struct berval		dn = { 0, NULL };
+	struct berval		pdn = { 0, NULL };
+	struct berval		ndn = { 0, NULL };
+
+	struct berval		newrdn = { 0, NULL };
+	struct berval		pnewrdn = { 0, NULL };
+	struct berval		nnewrdn = { 0, NULL };
+
+#if 0 /* currently unused */
+	struct berval		newSuperior = { 0, NULL };
+#endif
+	struct berval		pnewSuperior = { 0, NULL }; 
+#if 0 /* currently unused */
+	struct berval		nnewSuperior = { 0, NULL }; 
+#endif
+
+	struct berval		*pnewS = NULL;
+	struct berval		*nnewS = NULL;
+
+	Connection		*pConn = NULL;
+	Operation		*op = NULL;
+	Slapi_PBlock		*pPB = NULL;
+	Slapi_PBlock		*pSavePB = NULL;
+
+	Backend			*be;
+#if 0 /* currently unused */
+	Backend 		*newSuperior_be = NULL;
+#endif
+
+	int			manageDsaIt = 0;
+	int			isCritical;
+#if 0 /* currently unused */
+	const char 		*text = NULL;
+#endif
+
+	dn.bv_val = slapi_ch_strdup(olddn);
+	dn.bv_len = slapi_ch_stlen(olddn);
+
+	rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn );
+
+	if ( rc != LDAP_SUCCESS ) goto cleanup;
+
+	if ( ndn.bv_len == 0 ) {
+		rc = LDAP_UNWILLING_TO_PERFORM;
+		goto cleanup;
+	}
+
+	newrdn.bv_val = slapi_ch_strdup( lnewrdn );
+	newrdn.bv_len = slapi_ch_stlen( lnewrdn );
+
+	rc = dnPrettyNormal( NULL, &newrdn, &pnewrdn, &nnewrdn );
+
+	if ( rc != LDAP_SUCCESS ) goto cleanup;
+
+	if ( rdnValidate( &pnewrdn ) != LDAP_SUCCESS ) goto cleanup;
+
+	pConn = fakeConnection( NULL,  LDAP_REQ_MODRDN);
+	if ( pConn == NULL) {
+		rc = LDAP_NO_MEMORY;
+		goto cleanup;
+	}
+
+	op = (Operation *)pConn->c_pending_ops.stqh_first;
+	pPB = (Slapi_PBlock *)op->o_pb;
+	op->o_ctrls = controls;
+
+	if ( slapi_control_present( controls, 
+			SLAPI_CONTROL_MANAGEDSAIT_OID, NULL, &isCritical ) ) {
+		manageDsaIt = 1;
+	}
+
+	be = select_backend( &dn, manageDsaIt, 0 );
+	if ( be == NULL ) {
+		rc =  LDAP_PARTIAL_RESULTS;
+		goto cleanup;
+	}
+
+	op->o_ndn.bv_val = slapi_ch_strdup( be->be_rootdn.bv_val );
+	op->o_ndn.bv_len = be->be_rootdn.bv_len;
+	pConn->c_dn.bv_val = slapi_ch_strdup( be->be_rootdn.bv_val );
+	pConn->c_dn.bv_len = be->be_rootdn.bv_len;
+
+	suffix_alias( be, &ndn );
+
+	if ( be->be_modrdn ) {
+		int repl_user = be_isupdate( be, &op->o_ndn );
+		if ( !be->be_update_ndn.bv_len || repl_user ) {
+			rc = (*be->be_modrdn)( be, pConn, op, &pdn, &ndn,
+					&pnewrdn, &nnewrdn, deloldrdn, pnewS,
+					nnewS );
+			if ( rc == 0 ) {
+				struct slap_replog_moddn moddn;
+				moddn.newrdn = &pnewrdn;
+				moddn.deloldrdn = deloldrdn;
+				moddn.newsup = &pnewSuperior;
+				if ( log_change ) {
+					replog( be, op, &pdn, &ndn, &moddn );
+				}
+				rc = LDAP_SUCCESS;
+
+			} else {
+				rc = LDAP_OPERATIONS_ERROR;
+			}
+
+		} else {
+			rc = LDAP_REFERRAL;
+		}
+
+	} else {
+		rc = LDAP_UNWILLING_TO_PERFORM;
+	}
+
+cleanup:
+
+	if ( pPB != NULL ) {
+		slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
+	}
+	
+	if ( dn.bv_val ) ch_free( dn.bv_val );
+	if ( pdn.bv_val ) ch_free( pdn.bv_val );
+	if ( ndn.bv_val ) ch_free( ndn.bv_val );
+
+	if ( newrdn.bv_val ) ch_free( newrdn.bv_val );
+	if ( pnewrdn.bv_val ) ch_free( newrdn.bv_val );
+	if ( nnewrdn.bv_val ) ch_free( newrdn.bv_val );
+
+	if ( pConn != NULL ) {
+		if ( pConn->c_dn.bv_val ) slapi_ch_free( pConn->c_dn.bv_val );
+		if ( op ) {
+			if ( op->o_dn.bv_val ) slapi_ch_free( op->o_dn.bv_val );
+			slapi_ch_free( op );
+		}
+		pSavePB = pPB;
+		free( pConn );
+	}
+
+	return( pSavePB );
+#endif /* LDAP_SLAPI */
+	return NULL;
+}
+
+/* Function : slapi_modify_internal
+ *
+ * Description:	Plugin functions call this routine to modify an entry 
+ *				in the backend directly
+ * Return values : LDAP_SUCCESS
+ *                 LDAP_OPERAITONS_ERROR
+ *                 LDAP_NO_MEMORY
+ *                 LDAP_OTHER
+ *                 LDAP_UNWILLING_TO_PERFORM
+*/
+Slapi_PBlock *
+slapi_modify_internal(
+	char *ldn, 	
+	LDAPMod **mods, 
+	LDAPControl **controls, 
+	int log_change )
+{
+#if defined(LDAP_SLAPI)
+	int			i, rc = LDAP_SUCCESS;
+	Connection		*pConn = NULL;
+	Operation		*op = NULL;
+	Slapi_PBlock		*pPB = NULL;
+	Slapi_PBlock		*pSavePB = NULL;
+
+	struct berval dn = { 0, NULL };
+	struct berval pdn = { 0, NULL };
+	struct berval ndn = { 0, NULL };
+
+	int			manageDsaIt = 0;
+	int			isCritical;
+	Backend			*be;
+	struct berval		*bv;
+	struct berval   	**ppBV;
+	LDAPMod			*pMod;
+
+	Modifications		*modlist = NULL;
+	Modifications		**modtail = &modlist;
+	Modifications		tmp;
+
+	if ( mods == NULL || *mods == NULL || ldn == NULL ) {
+		rc = LDAP_OPERATIONS_ERROR ;
+		goto cleanup;
+	}
+
+	pConn = fakeConnection( NULL,  LDAP_REQ_MODIFY );
+	if ( pConn == NULL ) {
+		rc = LDAP_NO_MEMORY;
+		goto cleanup;
+	}
+
+	op = (Operation *)pConn->c_pending_ops.stqh_first;
+	pPB = (Slapi_PBlock *)op->o_pb;
+	op->o_ctrls = controls;
+
+	dn.bv_val = slapi_ch_strdup( ldn );
+	dn.bv_len = slapi_strlen( ldn );
+	rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn );
+	if ( rc != LDAP_SUCCESS ) goto cleanup;
+
+	if ( slapi_control_present( controls, 
+			SLAPI_CONTROL_MANAGEDSAIT_OID, NULL, &isCritical ) ) {
+        	manageDsaIt = 1;
+	}
+
+	be = select_backend( &dn, manageDsaIt, 0 );
+	if ( be == NULL ) {
+		rc =  LDAP_PARTIAL_RESULTS;
+		goto cleanup;
+    	}
+
+	op->o_ndn.bv_val = slapi_ch_strdup( be->be_rootdn.bv_val );
+	op->o_ndn.bv_len = be->be_rootdn.bv_len;
+	pConn->c_dn.bv_val = slapi_ch_strdup( be->be_rootdn.bv_val );
+	pConn->c_dn.bv_len = be->be_rootdn.bv_len;
+
+    	suffix_alias( be, &ndn );
+
+	for ( i = 0, pMod = mods[0]; rc == LDAP_SUCCESS && pMod != NULL; 
+			pMod = mods[++i] ) {
+		Modifications *mod;
+		if ( (pMod->mod_op & LDAP_MOD_BVALUES) != 0 ) {
+			/*
+			 * attr values are in berval format
+			 * convert an array of pointers to bervals
+			 * to an array of bervals
+			 */
+			rc = bvptr2obj( pMod->mod_bvalues, &bv );
+			if ( rc != LDAP_SUCCESS ) goto cleanup;
+			tmp.sml_type.bv_val = slapi_ch_strdup( pMod->mod_type );
+			tmp.sml_type.bv_len = slapi_ch_stlen( pMod->mod_type );
+			tmp.sml_bvalues = bv;
+
+			mod  = (Modifications *)ch_malloc( sizeof(Modifications) );
+
+			mod->sml_op = pMod->mod_op;
+			mod->sml_next = NULL;
+			mod->sml_desc = NULL;
+			mod->sml_type = tmp.sml_type;
+			mod->sml_bvalues = tmp.sml_bvalues;
+		} else { 
+			rc = ValuesToBValues( pMod->mod_values, &ppBV );
+			if ( rc != LDAP_SUCCESS ) goto cleanup;
+			rc = bvptr2obj( ppBV, &bv );
+			if ( rc != LDAP_SUCCESS ) goto cleanup;
+			tmp.sml_type.bv_val = slapi_ch_strdup( pMod->mod_type );
+			tmp.sml_type.bv_len = slapi_ch_stlen( pMod->mod_type );
+			tmp.sml_bvalues = bv;
+
+			mod  = (Modifications *) ch_malloc( sizeof(Modifications) );
+
+			mod->sml_op = pMod->mod_op;
+			mod->sml_next = NULL;
+			mod->sml_desc = NULL;
+			mod->sml_type = tmp.sml_type;
+			mod->sml_bvalues = tmp.sml_bvalues;
+
+			if ( ppBV != NULL ) {
+				ber_bvecfree( ppBV );
+			}
+		}
+		*modtail = mod;
+		modtail = &mod->sml_next;
+
+		switch( pMod->mod_op ) {
+		case LDAP_MOD_ADD:
+		if ( mod->sml_bvalues == NULL ) {
+			rc = LDAP_PROTOCOL_ERROR;
+			goto cleanup;
+		}
+
+		/* fall through */
+		case LDAP_MOD_DELETE:
+		case LDAP_MOD_REPLACE:
+		break;
+
+		default:
+			rc = LDAP_PROTOCOL_ERROR;
+			goto cleanup;
+		}
+	} 
+	*modtail = NULL;
+
+	if ( ndn.bv_len == 0 ) {
+		rc = LDAP_UNWILLING_TO_PERFORM;
+		goto cleanup;
+	}
+
+	if ( be->be_modify ) {
+		int repl_user = be_isupdate( be, &op->o_ndn );
+		if ( !be->be_update_ndn.bv_len || repl_user ) {
+			int update = be->be_update_ndn.bv_len;
+			const char *text = NULL;
+			char textbuf[SLAP_TEXT_BUFLEN];
+			size_t textlen = sizeof( textbuf );
+
+			rc = slap_mods_check( modlist, update,
+					&text, textbuf, textlen );
+			if (rc != LDAP_SUCCESS) {
+				goto cleanup;
+			}
+
+			if ( !repl_user ) {
+				rc = slap_mods_opattrs( be, op, modlist,
+						modtail, &text, textbuf, 
+						textlen );
+				if (rc != LDAP_SUCCESS) {
+					goto cleanup;
+				}
+			}
+			rc = (*be->be_modify)( be, pConn, op,
+					&pdn, &ndn, modlist );
+			if ( rc == 0 ) {
+				if ( log_change ) {
+					replog( be, op, &pdn, &ndn, modlist );
+				}
+				rc = LDAP_SUCCESS;
+			} else {
+				rc = LDAP_OPERATIONS_ERROR;
+			}
+		} else {
+			rc = LDAP_REFERRAL;
+		}
+	} else {
+		rc = LDAP_UNWILLING_TO_PERFORM;
+	}
+
+cleanup:
+
+	if ( pPB != NULL ) 
+		slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
+
+	if ( dn.bv_val ) ch_free( dn.bv_val );
+	if ( pdn.bv_val ) ch_free( pdn.bv_val );
+	if ( ndn.bv_val ) ch_free( ndn.bv_val );
+
+	if ( modlist != NULL ) slap_mods_free( modlist );
+
+	if ( pConn != NULL ) {
+		if ( pConn->c_dn.bv_val ) slapi_ch_free( pConn->c_dn.bv_val );
+		if ( op ) {
+			if ( op->o_dn.bv_val ) slapi_ch_free( op->o_dn.bv_val );
+			slapi_ch_free( op );
+		}
+		pSavePB = pPB;
+		free( pConn );
+	}
+
+	return ( pSavePB );
+
+#endif /* LDAP_SLAPI */
+	return NULL;
+}
+
+Slapi_PBlock *
+slapi_search_internal_bind(
+	char *bindDN, 
+	char *ldn, 
+	int scope, 
+	char *filStr, 
+	LDAPControl **controls, 
+	char **attrs, 
+	int attrsonly ) 
+{	
+#if defined(LDAP_SLAPI)
+	Backend			*be;
+	Connection		*c;
+	Operation		*op = NULL;
+	Slapi_PBlock		*ptr = NULL;		
+	Slapi_PBlock		*pSavePB = NULL;		
+	struct berval		dn = { 0, NULL };
+	struct berval		pdn = { 0, NULL };
+	struct berval		ndn = { 0, NULL };
+	Filter			*filter=NULL;
+	struct berval		fstr = { 0, NULL };
+	AttributeName		*an = NULL;
+	const char		*text = NULL;
+
+	int			deref=0;
+	int			sizelimit=-1, timelimit=-1;
+
+	int			manageDsaIt = 0; 
+	int			isCritical;
+
+	int			i, rc = LDAP_SUCCESS;
+	
+	c = fakeConnection( NULL, LDAP_REQ_SEARCH );
+	if (c == NULL) {
+		rc = LDAP_NO_MEMORY;
+		goto cleanup;
+	}
+
+	op = (Operation *)c->c_pending_ops.stqh_first;
+	ptr = (Slapi_PBlock *)op->o_pb;
+	op->o_ctrls = controls;
+
+	dn.bv_val = slapi_ch_strdup(ldn);
+	dn.bv_len = slapi_strlen(ldn);
+
+	rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn );
+	if (rc != LDAP_SUCCESS) goto cleanup;
+
+	if ( scope != LDAP_SCOPE_BASE && 
+		 	scope != LDAP_SCOPE_ONELEVEL && 
+		 	scope != LDAP_SCOPE_SUBTREE ) {
+		rc = LDAP_PROTOCOL_ERROR;
+		goto cleanup;
+	}
+
+	filter = slapi_str2filter(filStr);
+	if ( filter == NULL ) {
+		rc = LDAP_PROTOCOL_ERROR;
+		goto cleanup;
+	}
+
+	filter2bv( filter, &fstr );
+
+	for ( i = 0; attrs != NULL && attrs[i] != NULL; i++ ) {
+		; /* count the number of attributes */
+	}
+
+	if (i > 0) {
+		an = (AttributeName *)slapi_ch_calloc(1, sizeof(AttributeName));
+		for (i = 0; attrs[i] != 0; i++) {
+			an[i].an_desc = NULL;
+			an[i].an_oc = NULL;
+			an[i].an_name.bv_val = slapi_ch_strdup(attrs[i]);
+			an[i].an_name.bv_len = slapi_strlen(attrs[i]);
+			slap_bv2ad( &an[i].an_name, &an[i].an_desc, &text );
+		}
+	}
+
+	if ( scope == LDAP_SCOPE_BASE ) {
+		Entry *entry = NULL;
+
+		if ( ndn.bv_len == 0 ) {
+			rc = root_dse_info( c, &entry, &text );
+		}
+
+		if( rc != LDAP_SUCCESS ) {
+			send_ldap_result( c, op, rc, NULL, text, NULL, NULL );
+			goto cleanup;
+		} else if ( entry != NULL ) {
+			rc = test_filter( NULL, c, op, entry, filter );
+
+			if( rc == LDAP_COMPARE_TRUE ) {
+				send_search_entry( NULL, c, op, entry,
+						an, attrsonly, NULL );
+            		}
+
+			entry_free( entry );
+
+			send_ldap_result( c, op, LDAP_SUCCESS, 
+					NULL, NULL, NULL, NULL );
+
+			rc = LDAP_SUCCESS;
+
+			goto cleanup;
+		}
+	}
+
+	if ( !ndn.bv_len && default_search_nbase.bv_len ) {
+		ch_free( pdn.bv_val );
+		ch_free( ndn.bv_val );
+
+		ber_dupbv( &pdn, &default_search_base );
+		ber_dupbv( &ndn, &default_search_nbase );
+	}
+
+	if ( slapi_control_present( controls,
+			LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical ) ) {
+		manageDsaIt = 1;
+	}
+
+	be = select_backend( &dn, manageDsaIt, 0 );
+	if ( be == NULL ) {
+		if ( manageDsaIt == 1 ) {
+			rc = LDAP_NO_SUCH_OBJECT;
+		} else {
+			rc = LDAP_PARTIAL_RESULTS;
+		}
+		goto cleanup;
+	} 
+
+	op->o_ndn.bv_val = slapi_ch_strdup( be->be_rootdn.bv_val );
+	op->o_ndn.bv_len = be->be_rootdn.bv_len;
+	c->c_dn.bv_val = slapi_ch_strdup( be->be_rootdn.bv_val );
+	c->c_dn.bv_len = be->be_rootdn.bv_len;
+
+	if ( be->be_search ) {
+		rc = (*be->be_search)( be, c, op, &pdn, &ndn,
+			scope, deref, sizelimit, timelimit,
+			filter, &fstr, an, attrsonly );
+		if ( rc == 0 ) {
+			rc = LDAP_SUCCESS;
+		} else {
+			rc = LDAP_OPERATIONS_ERROR;
+		}
+	} else {
+		rc = LDAP_UNWILLING_TO_PERFORM;
+	}
+
+cleanup:
+
+	if ( ptr != NULL )
+		slapi_pblock_set( ptr, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
+
+	if ( dn.bv_val ) free( dn.bv_val );
+	if ( ndn.bv_val ) free( ndn.bv_val );
+	if ( pdn.bv_val ) free( pdn.bv_val );
+
+	if ( filter ) slapi_filter_free( filter, 1 );
+	if ( fstr.bv_val ) free ( fstr.bv_val );
+
+	if ( an != NULL ) free( an );
+
+	if ( c != NULL ) {
+		if ( c->c_dn.bv_val ) slapi_ch_free( c->c_dn.bv_val );
+		if ( op ) {
+			if ( op->o_ndn.bv_val ) slapi_ch_free( op->o_ndn.bv_val );
+			free( op );
+		}
+		pSavePB = ptr;
+		free( c );
+    	}
+	return( pSavePB );
+#endif /* LDAP_SLAPI */
+	return NULL;
+}
+
+Slapi_PBlock * 
+slapi_search_internal(
+	char *base,
+	int scope,
+	char *filStr, 
+	LDAPControl **controls,
+	char **attrs,
+	int attrsonly ) 
+{
+#if defined(LDAP_SLAPI)
+	return slapi_search_internal_bind( NULL, base, scope, filStr,
+			controls, attrs, attrsonly );
+#endif
+	return NULL;
+}
+
diff --git a/servers/slapd/slapi/slapi_ops.c.all b/servers/slapd/slapi/slapi_ops.c.all
new file mode 100644
index 0000000000..dcf16820c1
--- /dev/null
+++ b/servers/slapd/slapi/slapi_ops.c.all
@@ -0,0 +1,1303 @@
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ * (C) Copyright IBM Corp. 1997,2002
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is
+ * given to IBM Corporation. This software is provided ``as is''
+ * without express or implied warranty.
+ */
+
+#include "portable.h"
+#include "slapi_common.h"
+#include <slap.h>
+#include <slapi.h>
+#include <lber.h>
+#include "../../../libraries/liblber/lber-int.h"
+
+int
+bvptr2obj(	struct berval **bvptr, 
+			struct berval **bvobj);
+
+Slapi_PBlock *
+slapi_simple_bind_internal( char *dn, 
+							struct berval *cred, 		
+							int method, 
+							int version);
+
+
+Connection *
+fakeConnection(	char *DN, 
+				int OpType) 
+{ 
+	Connection *pConn, *c;
+
+	if((pConn = (Connection *) slapi_ch_calloc(sizeof(Connection))) == NULL)
+		return (Connection *)NULL;
+
+	LDAP_STAILQ_INIT(&c->c_pending_ops);
+	LDAP_STAILQ_INIT(&c->c_ops);
+
+	if((pConn->c_pending_ops.stqh_first=(Operation *) slapi_ch_calloc(sizeof(Operation))) == NULL) { 
+		slapi_ch_free( pConn );
+		return (Connection *)NULL;
+	}
+
+	if((pConn->c_pending_ops.stqh_first->o_pb=(Slapi_PBlock *) slapi_pblock_new()) == NULL) {
+		slapi_ch_free( pConn->c_pending_ops.stqh_first );
+		slapi_ch_free( pConn );
+		return (Connection *)NULL;
+	}
+
+	c = pConn;
+
+	c->c_ops->o_opid = 0;
+	c->c_ops->o_msgid = 0;
+	c->c_ops->o_next = NULL;
+	c->c_ops->o_tag = OpType;
+	i->c_ops->o_abandon = 0;
+
+	c->c_authmech.bv_val = NULL;
+	c->c_authmech.bv_len = 0;
+	c->c_dn.bv_val = NULL;
+	c->c_dn.bv_len = 0;
+	c->c_ndn.bv_val = NULL;
+	c->c_ndn.bv_len = 0;
+	c->c_cdn.bv_val = NULL;
+	c->c_cdn.bv_len = 0;
+	c->c_groups = NULL;
+
+	c->c_listener_url.bv_val = NULL;
+	c->c_listener_url.bv_len = 0;
+	c->c_peer_domain.bv_val = NULL;
+	c->c_peer_domain.bv_len = 0;
+	c->c_peer_name.bv_val = NULL;
+	c->c_peer_name.bv_len = 0;
+	c->c_sock_name.bv_val = NULL;
+	c->c_sock_name.bv_len = 0;
+
+	c->c_sasl_bind_mech.bv_val = NULL;
+	c->c_sasl_bind_mech.bv_len = 0;
+	c->c_sasl_context = NULL;
+	c->c_sasl_extra = NULL;
+
+	c->c_sb = ber_sockbuf_alloc( );
+
+	c->c_currentber = NULL;
+
+	c->c_struct_state = SLAP_C_UNUSED;
+
+	c->c_n_get = 0;
+	c->c_n_read = 0;
+	c->c_n_write = 0;
+
+	c->c_protocol = LDAP_VERSION3; 
+
+	time(&pConn->c_pending_ops.stqh_first->o_time);
+
+	pConn->c_send_ldap_result_v3 = (SEND_LDAP_RESULT_V3) internal_result_v3;
+	pConn->c_send_search_entry = (SEND_SEARCH_ENTRY) internal_search_entry;
+	pConn->c_send_ldap_search_result = (SEND_LDAP_SEARCH_RESULT) internal_search_result;
+	pConn->c_send_ldap_result_ext = (SEND_LDAP_RESULT_EXT) internal_result_ext;
+	pConn->c_send_ldap_search_reference = (SEND_SEARCH_REFERENCE) internal_search_reference;
+
+	return pConn;
+}
+
+
+/* Function : slapi_delete_internal
+ *
+ * Description : Plugin functions call this routine to delete an entry 
+ *               in the backend directly
+ * Return values : LDAP_SUCCESS
+ *                 LDAP_OPERAITONS_ERROR
+ *                 LDAP_NO_MEMORY
+ *                 LDAP_OTHER
+ *                 LDAP_UNWILLING_TO_PERFORM
+*/
+Slapi_PBlock *
+slapi_delete_internal(	char *ldn, 
+						LDAPControl **controls, 
+						int log_change)
+{
+
+	int				rc=LDAP_SUCCESS;
+	Backend			*be;
+	Slapi_PBlock	*pPB=NULL;
+	Slapi_PBlock	*pSavePB=NULL;
+	Connection		*pConn=NULL;
+	Operation		*op;
+
+	int				manageDsaIt = 0;
+    int				isCritical;
+
+	struct berval dn  = { 0, NULL };
+	struct berval pdn = { 0, NULL };
+	struct berval ndn = { 0, NULL };
+
+
+	if ( ldn == NULL ) {
+		rc = LDAP_OPERATIONS_ERROR; 
+	}
+
+	if ( rc == LDAP_SUCCESS ) {
+		pConn = fakeConnection( NULL,  LDAP_REQ_DELETE );
+	}
+
+	if ( pConn == NULL ) {
+		rc = LDAP_NO_MEMORY;
+	} else {
+		pPB = (Slapi_PBlock *)pConn->c_pending_ops.stqh_first->o_pb;
+		op = (Operation *)pConn->c_pending_ops.stqh_first;
+		op->o_ctrls = controls;
+
+		op->o_ndn.bv_val = slapi_strdup(be->be_update_ndn.bv_val);
+		op->o_ndn.bv_len = be->be_update_ndn.bv_len;
+		pConn->c_dn.bv_val = slapi_strdup(be->be_update_ndn.bv_val);
+		pConn->c_dn.bv_len = be->be_update_ndn.bv_len;
+	}
+	if ( rc == LDAP_SUCCESS ) {
+		dn.bv_val = slapi_strdup(ldn);
+		dn.bv_len = slapi_strlen(ldn);
+
+		rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn );
+
+		if( rc != LDAP_SUCCESS ) {
+#ifdef NEW_LOGGING
+			LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
+				"do_delete: conn %d  invalid dn (%s)\n",
+				conn->c_connid, dn.bv_val ));
+#else
+			Debug( LDAP_DEBUG_ANY,
+				"do_delete: invalid dn (%s)\n", dn.bv_val, 0, 0 );
+#endif
+		}
+	}
+
+	if( ndn.bv_len == 0 ) {
+#ifdef NEW_LOGGING
+		LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_delete: conn %d: "
+			"Attempt to delete root DSE.\n", conn->c_connid ));
+#else
+		Debug( LDAP_DEBUG_ANY, "Attempt to delete root DSE.\n", 0, 0, 0 );
+#endif
+		rc = LDAP_UNWILLING_TO_PERFORM;
+
+#ifdef SLAPD_SCHEMA_DN
+
+	} else if ( strcasecmp( ndn.bv_val, SLAPD_SCHEMA_DN ) == 0 ) {
+#ifdef NEW_LOGGING
+		LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_delete: conn %d: "
+				"Attempt to delete subschema subentry.\n", conn->c_connid ));
+#else
+		Debug( LDAP_DEBUG_ANY, "Attempt to delete subschema subentry.\n", 0, 0, 0 );
+#endif
+		rc = LDAP_UNWILLING_TO_PERFORM;
+
+#endif
+	}
+
+	if ( rc = slapi_control_present( controls, LDAP_MANAGEDSAIT_OID, NULL, &isCritical)){
+		manageDsaIt = 1; /* turn off referral */
+	}
+
+	if ( rc == LDAP_SUCCESS ) {
+		be = select_backend(&bv, manageDsaIt, 0);
+		if ( be == NULL ) rc =  LDAP_PARTIAL_RESULTS;
+	}
+
+	if ( rc == LDAP_SUCCESS ) {
+		rc = backend_check_restrictions( be, conn, op, NULL, &text ) ;
+	}
+
+	if ( rc == LDAP_SUCCESS ) {
+		rc = backend_check_referrals( be, conn, op, &pdn, &ndn );
+	}
+
+	suffix_alias( be, &ndn );
+
+	if ( be->be_delete ) {
+		/* do the update here */
+		int repl_user = be_isupdate( be, &op->o_ndn );
+#ifndef SLAPD_MULTIMASTER
+		if ( !be->be_update_ndn.bv_len || repl_user )
+#endif
+		{
+			if ( (*be->be_delete)( be, conn, op, &pdn, &ndn ) == 0 ) {
+#ifdef SLAPD_MULTIMASTER
+				if ( !be->be_update_ndn.bv_len || !repl_user )
+#endif
+				{
+					if (log_change) replog( be, op, &pdn, &ndn, NULL );
+                }
+            }
+#ifndef SLAPD_MULTIMASTER
+        } else {
+			rc = LDAP_REFERRAL;
+#endif
+        }
+	} else {
+		rc = LDAP_UNWILLING_TO_PERFORM;
+	}
+
+	if ( pPB != NULL ) { 
+		slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
+	}
+	if ( pConn != NULL ) {
+		if ( pConn->c_dn.bv_val )
+			slapi_ch_free( pConn->c_dn.bv_val );
+		if ( pConn->c_pending_ops.stqh_first->o_dn.bv_val )
+			slapi_ch_free( pConn->c_pending_ops.stqh_first->o_dn.bv_val );
+		if ( pConn->c_pending_ops.stqh_first )
+			slapi_ch_free( pConn->c_pending_ops.stqh_first );
+		if (dn.bv_val)
+			slapi_ch_free(dn.bv_val);
+		if (pdn.bv_val)
+			slapi_ch_free(pdn.bv_val);
+		if (ndn.bv_val)
+			slapi_ch_free(ndn_bv.val);
+		pSavePB = pPB;
+		free( pConn );
+	}
+	return( pSavePB );
+}
+
+/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+
+int
+internal_result_v3( Connection *conn, 
+					Operation *op, 
+					int err,
+					char *matched, 
+					char *text, 
+					char **referrals) 
+{
+	return LDAP_SUCCESS;
+}
+
+int
+internal_result_ext(	Connection *conn, 
+						Operation *op, 
+						int  errnum, 
+						char *respname, 
+						struct berval *response ) 
+{
+	return LDAP_SUCCESS;
+}
+
+int
+internal_search_reference(	Connection *conn, 
+							Operation *op, 
+							char **ref) 
+{
+	return LDAP_SUCCESS;
+}
+
+int
+internal_search_result(	Connection *conn, 
+						Operation *op,
+						int err, 
+						char *matched, 
+						char *text, 
+						int nentries) 
+{
+	slapi_pblock_set((Slapi_PBlock *)op->o_pb,SLAPI_NENTRIES,(void *)nentries);
+	return LDAP_SUCCESS;
+}
+
+
+int
+internal_search_entry(	Backend *be, 
+						Connection *conn, 
+						Operation *op, 
+						Entry *e, 
+		       			char **attrs, 
+						int attrsonly, 
+						char **denied_attrs) 
+{
+	char *ent2str = NULL;
+	int nentries = 0, len = 0, i = 0;
+	Slapi_Entry **head = NULL, **tp;
+	
+	if((ent2str=slapi_entry2str(e,&len)) == NULL) {
+		return SLAPD_NO_MEMORY;
+	}
+
+	slapi_pblock_get((Slapi_PBlock *)op->o_pb, SLAPI_NENTRIES, &nentries);
+	slapi_pblock_get((Slapi_PBlock *)op->o_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &head);
+	i=nentries + 1;
+	if(nentries == 0 ) {
+		if((tp=(Slapi_Entry **)slapi_ch_malloc(2 * sizeof(Slapi_Entry *))) == NULL) {
+			return SLAPD_NO_MEMORY;
+		}
+		if((tp[0]=(Slapi_Entry *)str2entry(ent2str)) == NULL) { 
+			return SLAPD_NO_MEMORY;
+		}
+	} else {
+		if((tp=(Slapi_Entry **)slapi_ch_realloc((char *)head,
+							(sizeof(Slapi_Entry *) * (i+1)))) == NULL) {
+			return SLAPD_NO_MEMORY;
+		}
+		if((tp[i-1]=(Slapi_Entry *)str2entry(ent2str)) == NULL) { 
+			return SLAPD_NO_MEMORY;
+		}
+	}
+	tp[i] = NULL;  
+              
+	slapi_pblock_set((Slapi_PBlock *)op->o_pb,SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,(void *)tp);
+	slapi_pblock_set((Slapi_PBlock *)op->o_pb,SLAPI_NENTRIES,(void *)i);
+	slapi_ch_free(ent2str);
+	return LDAP_SUCCESS;
+}
+
+
+/* 
+ * Function : freeModList 
+ * Free a list of LDAPMod structures which has the bvalue defined.
+*/
+static void 
+freeModList(	LDAPMod *pMod )
+{
+	LDAPMod *pNextMod;
+
+	while ( pMod != NULL ) {
+		pNextMod = pMod->mod_next;
+		free( pMod->mod_type );
+		ber_bvecfree( pMod->mod_bvalues );
+		free( pMod );
+		pMod = pNextMod;
+	}
+}
+
+
+/*
+ * Function : duplicateBVMod 
+ * Duplicate a LDAPMod structure in which the bervals are defined. 
+ * return code : LDAP_SUCEESS, 
+ *				 LDAP_OTHER, 
+ *				 LDAP_NO_MEMORY
+ */
+
+int 
+duplicateBVMod(	LDAPMod *pMod, 
+				LDAPMod **ppNewMod )
+{
+	int rc = LDAP_SUCCESS;
+	int i;
+	struct berval **ppNewBV;
+	struct berval *pNewBV;
+
+	if ( pMod == NULL ) {
+		rc = LDAP_OTHER;
+	} else {
+		*ppNewMod = (LDAPMod *)slapi_ch_malloc(sizeof(LDAPMod));
+		if ( *ppNewMod == NULL ) {
+			rc = LDAP_NO_MEMORY;
+		} else {
+			memset( (*ppNewMod),'\0',sizeof(LDAPMod) );
+			(*ppNewMod)->mod_op = pMod->mod_op;
+			(*ppNewMod)->mod_type = slapi_ch_strdup( pMod->mod_type);
+			if ( (*ppNewMod)->mod_type == NULL) {
+				rc = LDAP_NO_MEMORY;
+			} else {
+				if ( pMod->mod_bvalues == NULL ) {
+					(*ppNewMod)->mod_values = NULL; 
+				} else {
+					for ( i=0; pMod->mod_bvalues[i] != NULL; i++ ) {
+						;
+					}
+					ppNewBV = (struct berval **)slapi_ch_malloc( (i+1)*sizeof(struct berval *));
+					if ( ppNewBV == NULL ) {
+						rc = LDAP_NO_MEMORY;
+					} else {
+						for ( i=0; pMod->mod_bvalues[i] != NULL &&
+											rc == LDAP_SUCCESS; i++ ) {
+							pNewBV = (struct berval *)slapi_ch_malloc(sizeof(struct berval));
+							if ( pNewBV == NULL ) {
+								rc = LDAP_NO_MEMORY;
+							} else {
+								pNewBV->bv_val = slapi_ch_malloc(pMod->mod_bvalues[i]->bv_len+1);
+								if ( pNewBV->bv_val == NULL ) {
+									rc = LDAP_NO_MEMORY;
+								} else {
+									memset(pNewBV->bv_val,'\0',pMod->mod_bvalues[i]->bv_len+1);
+									pNewBV->bv_len = pMod->mod_bvalues[i]->bv_len;
+									memcpy(pNewBV->bv_val,pMod->mod_bvalues[i]->bv_val,pNewBV->bv_len);
+									ppNewBV[i] = pNewBV;
+								}
+							}
+						} /* for each bvalue */
+						if ( rc == LDAP_SUCCESS ) {
+							ppNewBV[i] = NULL;
+							(*ppNewMod)->mod_bvalues = ppNewBV;
+						}
+					}
+				}
+			}
+		}
+	}
+	return( rc );
+}
+
+/* 
+ * Function : ValuestoBValues 
+ * Convert an array of char ptrs to an array of berval ptrs.
+ * return value : LDAP_SUCCESS
+ *                LDAP_NO_MEMORY
+ *                LDAP_OTHER
+*/
+static int 
+ValuesToBValues(	char **ppValue, 
+					struct berval ***pppBV )
+{
+	int  rc = LDAP_SUCCESS;
+	int  i;
+	struct berval *pTmpBV;
+	struct berval **ppNewBV;
+
+	/* count the number of char ptrs. */
+	for ( i=0; ppValue != NULL && ppValue[i] != NULL; i++ ) {
+		;	/* NULL */
+	}
+
+	if ( i == 0 ) {
+		rc = LDAP_OTHER;
+	} else {
+		*pppBV = ppNewBV = (struct berval **)slapi_ch_malloc( (i+1)*(sizeof(struct berval *)) );
+		if ( *pppBV == NULL ) {
+			rc = LDAP_NO_MEMORY;
+		} else {
+			while ( ppValue != NULL && *ppValue != NULL && rc == LDAP_SUCCESS ) {
+				pTmpBV = (struct berval *)slapi_ch_malloc(sizeof(struct berval));
+				if ( pTmpBV == NULL) {
+					rc = LDAP_NO_MEMORY;
+				} else {
+					pTmpBV->bv_val = slapi_ch_strdup(*ppValue);
+					if ( pTmpBV->bv_val == NULL ) {
+						rc = LDAP_NO_MEMORY;
+					} else {
+						pTmpBV->bv_len = strlen(*ppValue);
+						*ppNewBV = pTmpBV;
+						ppNewBV++;
+					}
+					ppValue++;
+				}
+			}
+			/* null terminate the array of berval ptrs */
+			*ppNewBV = NULL;
+		}
+	}
+	return( rc );
+}
+
+
+/*
+ * Function : LDAPModToEntry 
+ * convert a dn plus an array of LDAPMod struct ptrs to an entry structure
+ * with a link list of the correspondent attributes.
+ * Return value : LDAP_SUCCESS
+ *                LDAP_NO_MEMORY
+ *                LDAP_OTHER
+*/
+Entry *
+LDAPModToEntry(	char *ldn, 
+				LDAPMod **mods )
+{
+	int				rc=LDAP_SUCCESS;
+	LDAPMod			*pMod;
+	Entry			*pEntry=NULL;
+	int				i,j;
+	struct berval	**ppSaveBV;
+	struct berval	**ppBV;
+	struct berval	*pTmpBV;
+	char			**ppValue;
+
+
+	AttributeDescription *ad;
+	struct berval *bv;
+	const char *text;
+
+    Modifications   *modlist = NULL;
+    Modifications   **modtail = &modlist;
+    Modifications   tmp;
+
+	struct berval dn = { 0, NULL };
+
+	dn.ber_val = slapi_ch_strdup(ldn);
+	dn.ber_len = slapi_ch_strlen(ldn);
+
+	pEntry = (Entry *) ch_calloc( 1, sizeof(Entry) );
+	if ( pEntry == NULL) {
+		rc = LDAP_NO_MEMORY;
+	} else {
+		rc = dnPrettyNormal( NULL, &dn, &e->e_name, &e->e_nname );
+		if( rc != LDAP_SUCCESS ) { 
+#ifdef NEW_LOGGING
+			LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
+				"LDAPModToEntry: invalid dn (%s)\n", dn.bv_val ));
+#else
+			Debug( LDAP_DEBUG_ANY, "LDAPModToEntry: invalid dn (%s)\n", dn.bv_val, 0, 0 ); 
+#endif
+			rc = LDAP_INVALID_DN_SYNTAX;
+		}
+	}
+	if ( rc == LDAP_SUCCESS ) {
+		for ( i=0, pMod=mods[0]; rc == LDAP_SUCCESS && pMod != NULL; pMod=mods[++i]) {
+			Modifications *mod;
+			if ( (pMod->mod_op & LDAP_MOD_BVALUES) != 0 ) {
+				/* attr values are in berval format */
+				/* convert an array of pointers to bervals to an array of bervals */
+				rc = bvptr2obj(pMod->mod_bvalues, &bv);
+				if (rc != LDAP_SUCCESS) break;
+				tmp.sml_type = pMod->mod_type;
+				tmp.sml_bvalues = bv;
+		
+				mod  = (Modifications *) ch_malloc( sizeof(Modifications) );
+
+				mod->sml_op = LDAP_MOD_ADD;
+				mod->sml_next = NULL;
+				mod->sml_desc = NULL;
+				mod->sml_type = tmp.sml_type;
+				mod->sml_bvalues = tmp.sml_bvalues;
+
+				*modtail = mod;
+				modtail = &mod->sml_next;
+
+			} else {
+            	/* attr values are in string format, need to be converted */
+				/* to an array of bervals */ 
+				if ( pMod->mod_values == NULL ) {
+					rc = LDAP_OTHER;
+				} else {
+					rc = ValuesToBValues( pMod->mod_values, &ppBV );
+					if (rc != LDAP_SUCCESS) break;
+					rc = bvptr2obj(ppBV, &bv);
+					if (rc != LDAP_SUCCESS) break;
+					tmp.sml_type = pMod->mod_type;
+					tmp.sml_bvalues = bv;
+		
+					mod  = (Modifications *) ch_malloc( sizeof(Modifications) );
+
+					mod->sml_op = LDAP_MOD_ADD;
+					mod->sml_next = NULL;
+					mod->sml_desc = NULL;
+					mod->sml_type = tmp.sml_type;
+					mod->sml_bvalues = tmp.sml_bvalues;
+
+					*modtail = mod;
+					modtail = &mod->sml_next;
+
+
+					if ( ppBV != NULL ) {
+						ber_bvecfree( ppBV );
+					}
+				}
+			}
+		} /* for each LDAPMod */
+	}
+
+    if( e->e_nname.bv_len == 0 ) 
+		rc = LDAP_ALREADY_EXISTS;
+
+	/* check if ManageDsaIt control is set  */
+	if ( rc = slapi_control_present( controls, LDAP_MANAGEDSAIT_OID, NULL, &isCritical)){
+		manageDsaIt = 1; /* turn off referral */
+	}
+
+	if ( rc == LDAP_SUCCESS ) {
+		be = select_backend(&bv, manageDsaIt, 0);
+		if ( be == NULL ) rc =  LDAP_PARTIAL_RESULTS;
+	}
+
+	if ( rc == LDAP_SUCCESS ) {
+		rc = backend_check_restrictions( be, conn, op, NULL, &text ) ;
+	}
+
+	if ( rc == LDAP_SUCCESS ) {
+		rc = backend_check_referrals( be, conn, op, &pdn, &ndn );
+	}
+
+
+	if ( rc != LDAP_SUCCESS ) {
+		if ( pEntry != NULL ) {
+			slapi_entry_free( pEntry );
+		}
+		pEntry = NULL;
+	}
+    return( pEntry );
+}
+
+/*xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
+
+Slapi_PBlock * 
+slapi_add_entry_internal(	Slapi_Entry *e, 
+							LDAPControl **controls, 
+							int log_changes) 
+{
+	int				rc=LDAP_SUCCESS, i;
+	Backend			*be;
+	Connection		*pConn=NULL;
+	Operation		*op;
+	Slapi_PBlock	*pPB=NULL, *pSavePB=NULL;
+	char			*pDn=NULL;
+	int				manageDsaIt = 0; /* referral is on */
+	int				isCritical;
+	struct berval	bv;
+	
+	/* check if ManageDsaIt control is set  */
+	if (slapi_control_present( controls, LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical)) {
+		 manageDsaIt = 1; /* turn off referral */
+	}
+
+	pConn = fakeConnection(NULL, LDAP_REQ_ADD);
+	if ( pConn == NULL ) {
+		rc = LDAP_NO_MEMORY;
+	} else { 
+		pPB = (Slapi_PBlock *)pConn->c_pending_ops.stqh_first->o_pb;
+		if (e == NULL) {
+			rc =  LDAP_OPERATIONS_ERROR;
+		} else {
+			if ( rc == LDAP_SUCCESS ) {
+				be = select_backend(&e->e_nname, manageDsaIt, 0);
+				if ( be == NULL ) {
+					rc = LDAP_PARTIAL_RESULTS;
+				} else if ( be->be_add == NULL) { 
+					rc = LDAP_UNWILLING_TO_PERFORM;
+				} else {
+					op = (Operation *)pConn->c_pending_ops.stqh_first;
+					op->o_ctrls = controls;
+					rc = (*be->be_add)( be, pConn, op, e );
+					if (rc == LDAP_SUCCESS)
+						Debug (LDAP_DEBUG_TRACE, " backend routine successful \n", 0, 0, 0);
+					else
+						Debug (LDAP_DEBUG_TRACE, " backend routine NOT successful \n", 0, 0, 0);
+				}
+			}
+		}
+	}
+	if ( pPB != NULL ) 
+		slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );   
+	if ( pDn != NULL )
+		slapi_ch_free( pDn );
+	if (bv.bv_val != NULL)
+		slapi_ch_free(bv.bv_val);
+	if ( pConn != NULL ) {
+		if ( pConn->c_dn.bv_val ) 
+			slapi_ch_free( pConn->c_dn.bv_val );
+		if ( pConn->c_pending_ops.stqh_first->o_dn.bv_val )
+			slapi_ch_free( pConn->c_pending_ops.stqh_first->o_dn.bv_val );
+		if ( pConn->c_pending_ops.stqh_first )
+			slapi_ch_free( pConn->c_pending_ops.stqh_first);
+		if (pConn->c_original_dn)
+			slapi_ch_free(pConn->c_original_dn); 
+		pSavePB = pPB;
+		free( pConn );
+	}
+	return( pSavePB );
+}
+
+
+
+Slapi_PBlock *
+slapi_add_internal(	char *dn, 
+					LDAPMod **mods, 
+					LDAPControl **controls, 
+					int log_changes  ) 
+{
+	LDAPMod			*pMod=NULL;
+	Slapi_PBlock	*pb=NULL;
+	Entry			*pEntry=NULL;
+	int				i, rc=LDAP_SUCCESS;
+
+
+	if(mods == NULL || *mods == NULL || dn == NULL || *dn == NULL) 
+		rc = LDAP_OPERATIONS_ERROR ;
+
+	if (rc == LDAP_SUCCESS) {
+		for (i=0, pMod=mods[0]; pMod != NULL; pMod=mods[++i] ) {
+			if ((pMod->mod_op & ~LDAP_MOD_BVALUES) != LDAP_MOD_ADD) {
+				rc = LDAP_OTHER;
+				break;
+			}
+		}
+	}
+
+	if ( rc == LDAP_SUCCESS ) {
+		if((pEntry = LDAPModToEntry( dn, mods )) == NULL) {
+			rc = LDAP_OTHER;
+		}
+	}
+
+	if(rc != LDAP_SUCCESS) {
+		pb = slapi_pblock_new();
+		slapi_pblock_set(pb, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
+	} else {
+		pb = slapi_add_entry_internal(pEntry, controls, log_changes);
+	}
+
+	if(pEntry) 
+		slapi_entry_free(pEntry);
+
+	return(pb);
+}
+
+
+/*dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd*/
+/* Function : slapi_modify_internal
+ *
+ * Description : Plugin functions call this routine to modify an entry in the backend directly
+ * Return values : LDAP_SUCCESS
+ *                 LDAP_OPERAITONS_ERROR
+ *                 LDAP_NO_MEMORY
+ *                 LDAP_OTHER
+ *                 LDAP_UNWILLING_TO_PERFORM
+*/
+Slapi_PBlock *
+slapi_modify_internal( char *dn, LDAPMod **mods, LDAPControl **controls, int log_change)
+{
+	int				rc=LDAP_SUCCESS;
+	int				i;
+	int				dnBadChar;
+	LDAPMod			*pMod;
+	LDAPMod			*pNewMod;
+	LDAPMod			*pTmpMod;
+	LDAPMod			*pSaveMod;
+	LDAPMod			*pModList=NULL;
+	Backend			*be;
+	Slapi_PBlock	*pPB=NULL;
+	Slapi_PBlock	*pSavePB=NULL;
+	Connection		*pConn=NULL;
+
+	int				manageDsaIt = 0;
+	int				isCritical;
+	struct berval	bv;
+	struct berval	*pbv;
+	AttributeDescription *ad;
+	const char		*text;
+	Operation		*op;
+	Modifications	*modlist = NULL;
+	Modifications	**modtail = &modlist;
+	struct berval pdn = { 0, NULL };
+	struct berval ndn = { 0, NULL };
+
+
+
+	pConn = fakeConnection( NULL,  LDAP_REQ_MODIFY );
+	if ( pConn == NULL ) {
+		rc = LDAP_NO_MEMORY;
+	} else {
+		pPB = (Slapi_PBlock *)pConn->c_pending_ops.stqh_first->o_pb;
+		if ( dn == NULL || mods == NULL || *mods == NULL ) {
+			rc = LDAP_OPERATIONS_ERROR; 
+		}
+	}
+	if ( rc == LDAP_SUCCESS ) {
+		dn_normalize( dn );
+
+		Debug(LDAP_DEBUG_TRACE,"slapi modifying object %s.\n", dn, 0, 0);
+		rc = dn_check(dn, &dnBadChar);
+		if ( rc == LDAP_SUCCESS ) {
+
+			/* We could be serving multiple database backends.  Select the
+			 * appropriate one, or send a referral to our "referral server"
+			 * if we don't hold it. 
+			 */
+
+			/* check if ManageDsaIt control is set  */
+			if ( slapi_control_present( controls,
+				 LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical ) ) {
+					manageDsaIt = 1; /* turn off referral */
+			}
+			bv.bv_val = strdup(dn);
+			bv.bv_len = strlen(dn);
+			be = select_backend(&bv, manageDsaIt, 0);
+			if ( be == NULL )  {
+				rc =  LDAP_PARTIAL_RESULTS;
+			} else if ( be->be_modify == NULL ) {
+				rc = LDAP_UNWILLING_TO_PERFORM;
+			}
+		}
+	}
+	if ( rc == LDAP_SUCCESS ) {
+		for ( i=0, pMod=mods[0]; pMod != NULL; pMod=mods[++i] ) {
+			if ( (pMod->mod_op & LDAP_MOD_BVALUES) != 0 ) {
+            	/* attr values are in berval format, merge them with the Entry's attr list */
+				rc = duplicateBVMod( pMod, &pNewMod );
+			} else {
+            	pNewMod = (LDAPMod *)slapi_ch_malloc(sizeof(LDAPMod));
+            	if ( pNewMod == NULL ) {
+					rc = LDAP_NO_MEMORY;
+				} else {
+					memset( pNewMod, '\0', sizeof(LDAPMod) );
+					pNewMod->mod_op = pMod->mod_op | LDAP_MOD_BVALUES;
+					pNewMod->mod_type = slapi_ch_strdup( pMod->mod_type );
+					if ( pNewMod->mod_type == NULL ) {
+						rc = LDAP_NO_MEMORY;
+					} else {
+						if ( (pMod->mod_op & ~LDAP_MOD_BVALUES) == LDAP_MOD_DELETE ) {
+							rc = ValuesToBValues( pMod->mod_values, &(pNewMod->mod_bvalues) );
+						} else {
+							if ( pMod->mod_values == NULL ) {
+								Debug(LDAP_DEBUG_TRACE,
+								 "slapi_modify_internal:mod_values is null\n",0, 0, 0);
+                      			rc = LDAP_OTHER;
+							} else {
+								rc = ValuesToBValues( pMod->mod_values, 
+													  &(pNewMod->mod_bvalues) );
+							}
+						}
+					}
+            	}
+			}
+			if ( rc == LDAP_SUCCESS ) {
+				/* add the new mod to the end of mod list */
+				if ( pModList == NULL ) {
+					pModList = pNewMod;
+				} else {
+					pTmpMod = pModList;
+					while ( pTmpMod != NULL ) {
+						pSaveMod = pTmpMod;
+						pTmpMod = pTmpMod->mod_next;
+					}
+					pSaveMod->mod_next = pNewMod;
+				}
+			}
+		}  /* for each LDAPMod */
+	}
+
+	if ( rc == LDAP_SUCCESS ) {
+		/* convert LDAPModList to Modification list */
+		pTmpMod = pModList;
+		while (pTmpMod != NULL) {
+			Modifications *mod;
+			mod = (Modifications *) ch_malloc( sizeof(Modifications) );
+			mod->sml_type.bv_val = ch_strdup(pTmpMod->mod_type);
+			mod->sml_type.bv_len = strlen(pTmpMod->mod_type);
+			mod->sml_op = pTmpMod->mod_op;
+			pbv = NULL;
+			rc = bvptr2obj(pTmpMod->mod_bvalues, &pbv);
+			mod->sml_bvalues = pbv;
+			ad = NULL;
+			rc = slap_str2ad(pTmpMod->mod_type, &ad, &text );
+			mod->sml_desc = ad;
+			*modtail = mod;
+			modtail = &mod->sml_next;
+			pTmpMod = pTmpMod->mod_next;
+		}
+		*modtail = NULL;
+	}
+
+   if ( rc == LDAP_SUCCESS ) {
+		op = (Operation *)pConn->c_pending_ops.stqh_first;
+		op->o_ctrls = controls;
+		Debug (LDAP_DEBUG_TRACE, "Calling backend routine \n", 0, 0, 0);
+		pdn.bv_val = ch_strdup(dn);
+		pdn.bv_len = strlen(dn);
+		ndn.bv_val = ch_strdup(dn);
+		ndn.bv_len = strlen(dn);
+		rc = (*be->be_modify)( be, pConn, op, &pdn, &ndn, modlist );
+		if (rc == LDAP_SUCCESS)
+             Debug (LDAP_DEBUG_TRACE, " backend routine successful \n", 0, 0, 0);
+		else
+			Debug (LDAP_DEBUG_TRACE, " backend routine NOT successful \n", 0, 0, 0);
+
+	} else { 
+		rc = LDAP_OPERATIONS_ERROR;
+	}
+
+   if ( pPB != NULL ) {
+      slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
+   }
+   if (pModList != NULL)  {
+         freeModList( pModList ); 
+   }
+   if ( pConn != NULL ) {
+      if ( pConn->c_dn.bv_val )
+         slapi_ch_free( pConn->c_dn.bv_val );
+      if ( pConn->c_original_dn )
+         slapi_ch_free( pConn->c_original_dn ); 
+      if ( pConn->c_pending_ops.stqh_first->o_dn.bv_val )
+         slapi_ch_free( pConn->c_pending_ops.stqh_first->o_dn.bv_val);
+      if ( pConn->c_pending_ops.stqh_first )
+         slapi_ch_free( pConn->c_pending_ops.stqh_first );
+      pSavePB = pPB;
+      free( pConn );
+   }
+   return( pSavePB );
+}
+
+
+/* Function : slapi_modrdn_internal
+ *
+ * Description : Plugin functions call this routine to modify the rdn 
+ *				 of an entry in the backend directly
+ * Return values : LDAP_SUCCESS
+ *                 LDAP_OPERAITONS_ERROR
+ *                 LDAP_NO_MEMORY
+ *                 LDAP_OTHER
+ *                 LDAP_UNWILLING_TO_PERFORM
+*/
+Slapi_PBlock *
+slapi_modrdn_internal(	char *olddn, 
+						char *newrdn, 
+						int deloldrdn, 
+						LDAPControl **controls, 
+						int log_change)
+{
+
+	int				rc=LDAP_SUCCESS;
+	int				dnBadChar;
+	Backend			*be;
+	char			*pDn=NULL;
+	Slapi_PBlock	*pPB=NULL;
+	Slapi_PBlock	*pSavePB=NULL;
+	Connection		*pConn=NULL;
+
+	int				manageDsaIt = 0;
+    int				isCritical;
+    struct berval	bv  = { 0, NULL };
+	Operation       *op;
+
+	struct berval dn = { 0, NULL };
+	struct berval ndn = { 0, NULL };
+	struct berval pdn = { 0, NULL };
+
+	struct berval newrdnO = { 0, NULL };
+	struct berval nnewrdnO = { 0, NULL };
+	struct berval pnewrdnO = { 0, NULL };
+
+	struct berval *nnewS = NULL;
+	struct berval *pnewS = NULL;
+
+	
+	dn.bv_val = ch_strdup(olddn);
+	if (dn.bv_val == NULL) {
+		rc = LDAP_NO_MEMORY;
+	} else {
+		dn.bv_len = strlen(olddn);
+	}
+
+	if (rc == LDAP_SUCCESS) {
+		newrdnO.bv_val = ch_strdup(newrdn);
+		if (newrdnO.bv_val == NULL) {
+			rc = LDAP_NO_MEMORY;
+		} else {
+			newrdnO.bv_len = strlen(newrdn);
+		}
+	} 
+
+	if (rc == LDAP_SUCCESS) {
+		rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn );
+	}
+
+	if (rc == LDAP_SUCCESS) {
+		rc = dnPrettyNormal( NULL, &newrdnO, &pnewrdnO, &nnewrdnO );
+	}
+		
+	if ( rc == LDAP_SUCCESS ) {
+		pConn = fakeConnection(NULL,  LDAP_REQ_MODRDN );
+	} 
+
+	if ( pConn == NULL ) {
+		rc = LDAP_NO_MEMORY;
+	} else {
+		pPB = (Slapi_PBlock *)pConn->c_pending_ops.stqh_first->o_pb;
+		if ( olddn == NULL || newrdn == NULL ) {
+			rc = LDAP_OPERATIONS_ERROR;
+		}
+	}
+	if ( rc == LDAP_SUCCESS ) {
+		Debug(LDAP_DEBUG_TRACE,"slapi modify rdn %s new RDN: %s.\n", olddn, newrdn, 0);
+		rc = dn_check(olddn, &dnBadChar);
+	}
+
+	if ( rc == LDAP_SUCCESS ) {
+
+		/* We could be serving multiple database backends.  Select the
+		 * appropriate one, or send a referral to our "referral server"
+		 * if we don't hold it. */
+
+		op = (Operation *)pConn->c_pending_ops.stqh_first;
+		op->o_ctrls = controls;
+
+		/* check if ManageDsaIt control is set  */
+		if ( slapi_control_present( controls,
+			 LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical ) ) {
+				manageDsaIt = 1; /* turn off referral */
+		}
+		be = select_backend(&bv, manageDsaIt, 0);
+		if ( be == NULL )  {
+			rc =  LDAP_PARTIAL_RESULTS;
+		}
+	}
+
+	if ( rc == LDAP_SUCCESS ) {
+		if ( be->be_modrdn == NULL ) {
+			rc = LDAP_UNWILLING_TO_PERFORM;
+		} else {
+			Debug (LDAP_DEBUG_TRACE, "Calling backend routine \n", 0, 0, 0);
+			rc = (*be->be_modrdn)( be, pConn, op, &pdn, &ndn,
+                                    &pnewrdnO, &nnewrdnO, deloldrdn, pnewS, nnewS );
+			if (rc == LDAP_SUCCESS)
+				Debug (LDAP_DEBUG_TRACE, " backend routine successful \n", 0, 0, 0);
+			else
+				Debug (LDAP_DEBUG_TRACE, " backend routine NOT successful \n", 0, 0, 0);
+		}
+	}
+
+	if (dn.bv_val)
+		ch_free(dn.bv_val);
+	if (pdn.bv_val)
+		ch_free(pdn.bv_val);
+	if (ndn.bv_val)
+		ch_free(ndn.bv_val);
+	if (newrdnO.bv_val)
+		ch_free(newrdnO.bv_val);
+	if (pnewrdnO.bv_val)
+		ch_free(newrdnO.bv_val);
+	if (nnewrdnO.bv_val)
+		ch_free(newrdnO.bv_val);
+
+	if ( pPB != NULL ) { 
+		slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
+	}
+	if ( pConn != NULL ) {
+		if ( pConn->c_dn.bv_val )
+			slapi_ch_free( pConn->c_dn.bv_val );
+		if (pConn->c_original_dn)
+			slapi_ch_free(pConn->c_original_dn);
+		if ( pConn->c_pending_ops.stqh_first->o_dn.bv_val )
+			slapi_ch_free( pConn->c_pending_ops.stqh_first->o_dn.bv_val );
+		if ( pConn->c_pending_ops.stqh_first )
+			slapi_ch_free( pConn->c_pending_ops.stqh_first );
+		pSavePB = pPB;
+		free( pConn );
+	}
+	return( pSavePB );
+}
+
+Slapi_PBlock * 
+slapi_search_internal( char *base, int scope, char *filStr, 
+					   LDAPControl **controls, char **attrs, int attrsonly ) 
+{
+	return slapi_search_internal_bind(NULL,base,scope,filStr,controls, attrs,attrsonly);
+}
+
+Slapi_PBlock *
+slapi_search_internal_bind( char *bindDN, char *b, int scope, char *filStr, 
+							 LDAPControl **controls, char **attrs, int attrsonly ) 
+{	
+	Slapi_PBlock	*ptr;		
+	Connection		*c;
+	Backend			*be;
+	Filter			*filter=NULL;
+	int				i, deref=0, sizelimit=-1, timelimit=-1, rc, dnCheckJunk=0;
+	int				manageDsaIt = 0; 
+	int				isCritical;
+	struct berval	bv;
+	Operation		*op;
+
+	struct berval base = { 0, NULL };
+	struct berval pbase = { 0, NULL };
+	struct berval nbase = { 0, NULL };
+	AttributeName   *an;
+	const char      *text;
+	struct berval   fstr = { 0, NULL };
+
+
+	
+	c=fakeConnection(bindDN,LDAP_REQ_SEARCH);
+
+	if ( c == NULL ) { 
+		rc = LDAP_NO_MEMORY;
+	} else {
+		ptr = (Slapi_PBlock *)c->c_pending_ops.stqh_first->o_pb;
+    }
+
+	/* check if ManageDsaIt control is set  */
+	if ( rc = slapi_control_present( controls, 
+									 LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical ) ) {
+		manageDsaIt = 1; /* turn off referral */
+	}
+	if ( scope != LDAP_SCOPE_BASE && scope != LDAP_SCOPE_ONELEVEL
+									&& scope != LDAP_SCOPE_SUBTREE ) {
+		slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)LDAP_PROTOCOL_ERROR);
+		return ptr;
+	}
+
+	dn_normalize( b );
+	rc=dn_check(b, &dnCheckJunk);
+	if(rc != LDAP_SUCCESS) {
+		slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)rc);
+		return ptr;
+	}
+
+	if ( attrs != NULL ) {
+		for ( i = 0; attrs[i] != NULL; i++ )
+			attr_normalize( attrs[i] );
+	}
+	if((filter=slapi_str2filter(filStr)) == NULL) {
+		slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)LDAP_PROTOCOL_ERROR);
+		return ptr;
+	}
+	bv.bv_val = ch_strdup(b);
+	bv.bv_len = strlen(b);
+	/* check if ManageDsaIt control is set  */
+	if ( slapi_control_present( controls,
+		LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical ) ) {
+		manageDsaIt = 1; /* turn off referral */
+	}
+
+	if ((be = select_backend( &bv, manageDsaIt, 0 )) == NULL) {
+                if ( manageDsaIt == 1 ) { /* referral turned off */
+                        slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)LDAP_NO_SUCH_OBJECT);
+                } else {
+                        slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)LDAP_PARTIAL_RESULTS);
+                }
+		return ptr;
+	} else if ( be->be_search == NULL ) {
+		slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)LDAP_UNWILLING_TO_PERFORM);
+		return ptr;
+	} else {
+
+		base.bv_val = ch_strdup(b);
+		base.bv_len = strlen(b);
+		rc = dnPrettyNormal( NULL, &base, &pbase, &nbase );
+		for (i = 0; attrs[i] != 0; i++) {
+			an[i].an_desc = NULL;
+			an[i].an_name.bv_val = ch_strdup(attrs[i]);
+			an[i].an_name.bv_len = strlen(attrs[i]);
+			slap_bv2ad(&an[i].an_name, &an[i].an_desc, &text);
+		}
+		fstr.bv_val = ch_strdup(filStr);
+		fstr.bv_len = strlen(filStr);
+		rc = (*be->be_search)( be, c, op, &pbase, &nbase, scope, deref, 
+					sizelimit, timelimit, filter, &fstr, an, attrsonly );
+	} 
+	slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)rc); 
+        if ( c->c_pending_ops.stqh_first ){
+          if(c->c_dn.bv_val)
+            slapi_ch_free(c->c_dn.bv_val);
+          if (c->c_original_dn)
+            slapi_ch_free(c->c_original_dn); 
+          if(c->c_pending_ops.stqh_first->o_dn.bv_val)
+            slapi_ch_free(c->c_pending_ops.stqh_first->o_dn.bv_val);
+          slapi_ch_free( c->c_pending_ops.stqh_first );
+        }
+	slapi_ch_free((void **)c);
+	if (filter) 
+		slapi_filter_free(filter,1);
+	return ptr;	
+}
+
+/*
+ Function : slapi_get_supported_extended_ops
+ Description : This function returns a pointer points to an array of Null terminated char pointers.
+               Each char pointer points to an oid of an extended operation.
+               If there is no defined extended operaitons, this routine returns NULL. 
+ Input : none
+ Output : pointer to an null terminated char pointer array or null.
+ Notes: The caller of this routine needs to free the retuned array pointer, but
+        should not free the pointers inside the array.
+*/
+char
+**slapi_get_supported_extended_ops(void)
+{
+
+	ExtendedOp   *pTmpExtOp;
+	int          numExtOps = 0;
+	int          i=0;
+	char         **ppExtOpOID = NULL;
+
+	if ( pGExtendedOps != NULL ) {
+		pTmpExtOp = pGExtendedOps;
+			while ( pTmpExtOp != NULL ) {
+				numExtOps++;
+				pTmpExtOp = pTmpExtOp->ext_next;
+			}
+
+		if ( numExtOps > 0 ) {
+			ppExtOpOID = (char **)slapi_ch_malloc( (numExtOps+1) * sizeof(char *) );
+			if ( ppExtOpOID != NULL ) {
+				pTmpExtOp = pGExtendedOps;
+				while ( pTmpExtOp != NULL ) {
+					ppExtOpOID[i] = pTmpExtOp->ext_oid;
+					i++;
+					pTmpExtOp = pTmpExtOp->ext_next;
+				}
+				ppExtOpOID[i] = NULL;
+			}
+		}
+	}
+
+	return( ppExtOpOID );
+}
+
+Slapi_PBlock *
+slapi_simple_bind_internal( char *d, struct berval *cred, int method, int version)
+{
+
+	int				rc=LDAP_SUCCESS;
+	Connection		*pConn=NULL;
+	Backend			*be;
+	Slapi_PBlock	*pPB=NULL;
+	int				dnBadChar;
+
+	int             isCritical;
+	struct berval   bv;
+	struct berval 	dn = { 0, NULL };
+	struct berval 	pdn = { 0, NULL };
+	struct berval 	ndn = { 0, NULL };
+	Operation		*op;
+
+
+	pConn = fakeConnection(NULL, LDAP_REQ_BIND );
+
+	if ( pConn == NULL ) {
+		rc = LDAP_NO_MEMORY;
+	} else {
+		pPB = (Slapi_PBlock *)pConn->c_pending_ops.stqh_first->o_pb;
+		pConn->c_version = version;
+		op = (Operation *)pConn->c_pending_ops.stqh_first;
+	}
+
+	if ( d == NULL ) {
+		rc = LDAP_OPERATIONS_ERROR;
+	} else {
+		dn.bv_val = ch_strdup (d);
+		dn.bv_len = strlen(d);
+		rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn );
+	}
+
+	if ( rc == LDAP_SUCCESS ) {
+		be = select_backend(&ndn, 0, 0 );
+		if ( be == NULL )  {
+			rc =  LDAP_PARTIAL_RESULTS;
+		} else if ( be->be_bind == NULL  ) {
+			rc = LDAP_UNWILLING_TO_PERFORM;
+		}
+	}
+
+	rc = (*be->be_bind)( be, pConn, op,
+					&pdn, &ndn, method, cred, NULL );
+
+	if (rc == LDAP_SUCCESS) {
+		pConn->c_version = version;
+		pConn->c_dn.bv_val = strdup( d );
+		pConn->c_dn.bv_len = strlen( d );
+		if (pConn->c_dn.bv_val == NULL) {
+			rc = LDAP_NO_MEMORY;
+			Debug (LDAP_DEBUG_TRACE, " backend routine successful, but has no more memory \n",0, 0, 0);
+		} 
+		Debug (LDAP_DEBUG_TRACE, " backend routine NOT successful \n", 0, 0, 0);
+	}
+
+	if ( pPB != NULL )
+       slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
+
+   return(pPB);
+
+}
+
diff --git a/servers/slapd/slapi/slapi_ops.c.save b/servers/slapd/slapi/slapi_ops.c.save
new file mode 100644
index 0000000000..4833d005ae
--- /dev/null
+++ b/servers/slapd/slapi/slapi_ops.c.save
@@ -0,0 +1,1271 @@
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ * (C) Copyright IBM Corp. 1997,2002
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is
+ * given to IBM Corporation. This software is provided ``as is''
+ * without express or implied warranty.
+ */
+
+#include "portable.h"
+#include "slapi_common.h"
+#include <slap.h>
+#include <slapi.h>
+#include <lber.h>
+#include "../../../libraries/liblber/lber-int.h"
+
+
+int
+bvptr2obj(	struct berval **bvptr, 
+			struct berval **bvobj);
+
+Slapi_PBlock *
+slapi_simple_bind_internal( char *dn, 
+							struct berval *cred, 		
+							int method, 
+							int version);
+
+int
+internal_result_v3( Connection *conn, 
+					Operation *op, 
+					int err,
+					char *matched, 
+					char *text, 
+					char **referrals) 
+{
+	return LDAP_SUCCESS;
+}
+
+
+
+int
+internal_search_entry(	Backend *be, 
+						Connection *conn, 
+						Operation *op, 
+						Entry *e, 
+		       			char **attrs, 
+						int attrsonly, 
+						char **denied_attrs) 
+{
+	char *ent2str = NULL;
+	int nentries = 0, len = 0, i = 0;
+	Slapi_Entry **head = NULL, **tp;
+	
+	if((ent2str=slapi_entry2str(e,&len)) == NULL) {
+		return SLAPD_NO_MEMORY;
+	}
+
+	slapi_pblock_get((Slapi_PBlock *)op->o_pb, SLAPI_NENTRIES, &nentries);
+	slapi_pblock_get((Slapi_PBlock *)op->o_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &head);
+	i=nentries + 1;
+	if(nentries == 0 ) {
+		if((tp=(Slapi_Entry **)slapi_ch_malloc(2 * sizeof(Slapi_Entry *))) == NULL) {
+			return SLAPD_NO_MEMORY;
+		}
+		if((tp[0]=(Slapi_Entry *)str2entry(ent2str)) == NULL) { 
+			return SLAPD_NO_MEMORY;
+		}
+	} else {
+		if((tp=(Slapi_Entry **)slapi_ch_realloc((char *)head,
+							(sizeof(Slapi_Entry *) * (i+1)))) == NULL) {
+			return SLAPD_NO_MEMORY;
+		}
+		if((tp[i-1]=(Slapi_Entry *)str2entry(ent2str)) == NULL) { 
+			return SLAPD_NO_MEMORY;
+		}
+	}
+	tp[i] = NULL;  
+              
+	slapi_pblock_set((Slapi_PBlock *)op->o_pb,SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,(void *)tp);
+	slapi_pblock_set((Slapi_PBlock *)op->o_pb,SLAPI_NENTRIES,(void *)i);
+	slapi_ch_free(ent2str);
+	return LDAP_SUCCESS;
+}
+
+int
+internal_search_result(	Connection *conn, 
+						Operation *op,
+						int err, 
+						char *matched, 
+						char *text, 
+						int nentries) 
+{
+	slapi_pblock_set((Slapi_PBlock *)op->o_pb,SLAPI_NENTRIES,(void *)nentries);
+	return LDAP_SUCCESS;
+}
+
+
+int
+internal_result_ext(	Connection *conn, 
+						Operation *op, 
+						int  errnum, 
+						char *respname, 
+						struct berval *response ) 
+{
+	return LDAP_SUCCESS;
+}
+
+
+int
+internal_search_reference(	Connection *conn, 
+							Operation *op, 
+							char **ref) 
+{
+	return LDAP_SUCCESS;
+}
+
+Connection *
+fakeConnection(	char *DN, 
+				int OpType) 
+{ 
+	Connection *pConn, *c;
+
+	if((pConn = (Connection *) slapi_ch_calloc(1, sizeof(Connection))) == NULL)
+		return (Connection *)NULL;
+
+	LDAP_STAILQ_INIT(&c->c_pending_ops);
+	LDAP_STAILQ_INIT(&c->c_ops);
+
+	if((pConn->c_pending_ops.stqh_first=(Operation *) slapi_ch_calloc(1, sizeof(Operation))) == NULL) { 
+		slapi_ch_free( pConn );
+		return (Connection *)NULL;
+	}
+
+	if((pConn->c_pending_ops.stqh_first->o_pb=(Slapi_PBlock *) slapi_pblock_new()) == NULL) {
+		slapi_ch_free( pConn->c_pending_ops.stqh_first );
+		slapi_ch_free( pConn );
+		return (Connection *)NULL;
+	}
+
+	c = pConn;
+
+	c->c_pending_ops.stqh_first->o_tag = OpType;
+	c->c_sb = ber_sockbuf_alloc( );
+	c->c_protocol = LDAP_VERSION3; 
+
+	time(&pConn->c_pending_ops.stqh_first->o_time);
+
+	pConn->c_send_ldap_result = (SEND_LDAP_RESULT) internal_result_v3;
+	pConn->c_send_search_entry = (SEND_SEARCH_ENTRY) internal_search_entry;
+	pConn->c_send_search_result = (SEND_SEARCH_RESULT) internal_search_result;
+	pConn->c_send_ldap_extended = (SEND_LDAP_EXTENDED) internal_result_ext;
+	pConn->c_send_search_reference = (SEND_SEARCH_REFERENCE) internal_search_reference;
+
+	return pConn;
+}
+
+
+/* Function : slapi_delete_internal
+ *
+ * Description : Plugin functions call this routine to delete an entry 
+ *               in the backend directly
+ * Return values : LDAP_SUCCESS
+ *                 LDAP_OPERAITONS_ERROR
+ *                 LDAP_NO_MEMORY
+ *                 LDAP_OTHER
+ *                 LDAP_UNWILLING_TO_PERFORM
+*/
+Slapi_PBlock *
+slapi_delete_internal(	char *ldn, 
+						LDAPControl **controls, 
+						int log_change)
+{
+
+	int				rc=LDAP_SUCCESS;
+	Backend			*be;
+	Slapi_PBlock	*pPB=NULL;
+	Slapi_PBlock	*pSavePB=NULL;
+	Connection		*pConn=NULL;
+	Operation		*op;
+
+	int				manageDsaIt = 0;
+    int				isCritical;
+
+	struct berval dn  = { 0, NULL };
+	struct berval pdn = { 0, NULL };
+	struct berval ndn = { 0, NULL };
+
+
+	if ( ldn == NULL ) {
+		rc = LDAP_OPERATIONS_ERROR; 
+	}
+
+	if ( rc == LDAP_SUCCESS ) {
+		pConn = fakeConnection( NULL,  LDAP_REQ_DELETE );
+	}
+
+	if ( pConn == NULL ) {
+		rc = LDAP_NO_MEMORY;
+	} else {
+		pPB = (Slapi_PBlock *)pConn->c_pending_ops.stqh_first->o_pb;
+		op = (Operation *)pConn->c_pending_ops.stqh_first;
+		op->o_ctrls = controls;
+
+		op->o_ndn.bv_val = slapi_strdup(be->be_update_ndn.bv_val);
+		op->o_ndn.bv_len = be->be_update_ndn.bv_len;
+		pConn->c_dn.bv_val = slapi_strdup(be->be_update_ndn.bv_val);
+		pConn->c_dn.bv_len = be->be_update_ndn.bv_len;
+	}
+	if ( rc == LDAP_SUCCESS ) {
+		dn.bv_val = slapi_strdup(ldn);
+		dn.bv_len = slapi_strlen(ldn);
+
+		rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn );
+
+		if( rc != LDAP_SUCCESS ) {
+#ifdef NEW_LOGGING
+			LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
+				"do_delete: conn %d  invalid dn (%s)\n",
+				conn->c_connid, dn.bv_val ));
+#else
+			Debug( LDAP_DEBUG_ANY,
+				"do_delete: invalid dn (%s)\n", dn.bv_val, 0, 0 );
+#endif
+		}
+	}
+
+	if( ndn.bv_len == 0 ) {
+#ifdef NEW_LOGGING
+		LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_delete: conn %d: "
+			"Attempt to delete root DSE.\n", conn->c_connid ));
+#else
+		Debug( LDAP_DEBUG_ANY, "Attempt to delete root DSE.\n", 0, 0, 0 );
+#endif
+		rc = LDAP_UNWILLING_TO_PERFORM;
+
+#ifdef SLAPD_SCHEMA_DN
+
+	} else if ( strcasecmp( ndn.bv_val, SLAPD_SCHEMA_DN ) == 0 ) {
+#ifdef NEW_LOGGING
+		LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_delete: conn %d: "
+				"Attempt to delete subschema subentry.\n", conn->c_connid ));
+#else
+		Debug( LDAP_DEBUG_ANY, "Attempt to delete subschema subentry.\n", 0, 0, 0 );
+#endif
+		rc = LDAP_UNWILLING_TO_PERFORM;
+
+#endif
+	}
+
+	if ( rc = slapi_control_present( controls, LDAP_MANAGEDSAIT_OID, NULL, &isCritical)){
+		manageDsaIt = 1; /* turn off referral */
+	}
+
+	if ( rc == LDAP_SUCCESS ) {
+		be = select_backend(&bv, manageDsaIt, 0);
+		if ( be == NULL ) rc =  LDAP_PARTIAL_RESULTS;
+	}
+
+	if ( rc == LDAP_SUCCESS ) {
+		rc = backend_check_restrictions( be, conn, op, NULL, &text ) ;
+	}
+
+	if ( rc == LDAP_SUCCESS ) {
+		rc = backend_check_referrals( be, conn, op, &pdn, &ndn );
+	}
+
+	suffix_alias( be, &ndn );
+
+	if ( be->be_delete ) {
+		/* do the update here */
+		int repl_user = be_isupdate( be, &op->o_ndn );
+#ifndef SLAPD_MULTIMASTER
+		if ( !be->be_update_ndn.bv_len || repl_user )
+#endif
+		{
+			if ( (*be->be_delete)( be, conn, op, &pdn, &ndn ) == 0 ) {
+#ifdef SLAPD_MULTIMASTER
+				if ( !be->be_update_ndn.bv_len || !repl_user )
+#endif
+				{
+					if (log_change) replog( be, op, &pdn, &ndn, NULL );
+                }
+            }
+#ifndef SLAPD_MULTIMASTER
+        } else {
+			rc = LDAP_REFERRAL;
+#endif
+        }
+	} else {
+		rc = LDAP_UNWILLING_TO_PERFORM;
+	}
+
+	if ( pPB != NULL ) { 
+		slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
+	}
+	if ( pConn != NULL ) {
+		if ( pConn->c_dn.bv_val )
+			slapi_ch_free( pConn->c_dn.bv_val );
+		if ( pConn->c_pending_ops.stqh_first->o_dn.bv_val )
+			slapi_ch_free( pConn->c_pending_ops.stqh_first->o_dn.bv_val );
+		if ( pConn->c_pending_ops.stqh_first )
+			slapi_ch_free( pConn->c_pending_ops.stqh_first );
+		if (dn.bv_val)
+			slapi_ch_free(dn.bv_val);
+		if (pdn.bv_val)
+			slapi_ch_free(pdn.bv_val);
+		if (ndn.bv_val)
+			slapi_ch_free(ndn_bv.val);
+		pSavePB = pPB;
+		free( pConn );
+	}
+	return( pSavePB );
+}
+
+#if 0
+/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+
+
+/* 
+ * Function : freeModList 
+ * Free a list of LDAPMod structures which has the bvalue defined.
+*/
+static void 
+freeModList(	LDAPMod *pMod )
+{
+	LDAPMod *pNextMod;
+
+	while ( pMod != NULL ) {
+		pNextMod = pMod->mod_next;
+		free( pMod->mod_type );
+		ber_bvecfree( pMod->mod_bvalues );
+		free( pMod );
+		pMod = pNextMod;
+	}
+}
+
+
+/*
+ * Function : duplicateBVMod 
+ * Duplicate a LDAPMod structure in which the bervals are defined. 
+ * return code : LDAP_SUCEESS, 
+ *				 LDAP_OTHER, 
+ *				 LDAP_NO_MEMORY
+ */
+
+int 
+duplicateBVMod(	LDAPMod *pMod, 
+				LDAPMod **ppNewMod )
+{
+	int rc = LDAP_SUCCESS;
+	int i;
+	struct berval **ppNewBV;
+	struct berval *pNewBV;
+
+	if ( pMod == NULL ) {
+		rc = LDAP_OTHER;
+	} else {
+		*ppNewMod = (LDAPMod *)slapi_ch_malloc(sizeof(LDAPMod));
+		if ( *ppNewMod == NULL ) {
+			rc = LDAP_NO_MEMORY;
+		} else {
+			memset( (*ppNewMod),'\0',sizeof(LDAPMod) );
+			(*ppNewMod)->mod_op = pMod->mod_op;
+			(*ppNewMod)->mod_type = slapi_ch_strdup( pMod->mod_type);
+			if ( (*ppNewMod)->mod_type == NULL) {
+				rc = LDAP_NO_MEMORY;
+			} else {
+				if ( pMod->mod_bvalues == NULL ) {
+					(*ppNewMod)->mod_values = NULL; 
+				} else {
+					for ( i=0; pMod->mod_bvalues[i] != NULL; i++ ) {
+						;
+					}
+					ppNewBV = (struct berval **)slapi_ch_malloc( (i+1)*sizeof(struct berval *));
+					if ( ppNewBV == NULL ) {
+						rc = LDAP_NO_MEMORY;
+					} else {
+						for ( i=0; pMod->mod_bvalues[i] != NULL &&
+											rc == LDAP_SUCCESS; i++ ) {
+							pNewBV = (struct berval *)slapi_ch_malloc(sizeof(struct berval));
+							if ( pNewBV == NULL ) {
+								rc = LDAP_NO_MEMORY;
+							} else {
+								pNewBV->bv_val = slapi_ch_malloc(pMod->mod_bvalues[i]->bv_len+1);
+								if ( pNewBV->bv_val == NULL ) {
+									rc = LDAP_NO_MEMORY;
+								} else {
+									memset(pNewBV->bv_val,'\0',pMod->mod_bvalues[i]->bv_len+1);
+									pNewBV->bv_len = pMod->mod_bvalues[i]->bv_len;
+									memcpy(pNewBV->bv_val,pMod->mod_bvalues[i]->bv_val,pNewBV->bv_len);
+									ppNewBV[i] = pNewBV;
+								}
+							}
+						} /* for each bvalue */
+						if ( rc == LDAP_SUCCESS ) {
+							ppNewBV[i] = NULL;
+							(*ppNewMod)->mod_bvalues = ppNewBV;
+						}
+					}
+				}
+			}
+		}
+	}
+	return( rc );
+}
+
+/* 
+ * Function : ValuestoBValues 
+ * Convert an array of char ptrs to an array of berval ptrs.
+ * return value : LDAP_SUCCESS
+ *                LDAP_NO_MEMORY
+ *                LDAP_OTHER
+*/
+
+static int 
+ValuesToBValues(	char **ppValue, 
+					struct berval ***pppBV )
+{
+	int  rc = LDAP_SUCCESS;
+	int  i;
+	struct berval *pTmpBV;
+	struct berval **ppNewBV;
+
+	/* count the number of char ptrs. */
+	for ( i=0; ppValue != NULL && ppValue[i] != NULL; i++ ) {
+		;	/* NULL */
+	}
+
+	if ( i == 0 ) {
+		rc = LDAP_OTHER;
+	} else {
+		*pppBV = ppNewBV = (struct berval **)slapi_ch_malloc( (i+1)*(sizeof(struct berval *)) );
+		if ( *pppBV == NULL ) {
+			rc = LDAP_NO_MEMORY;
+		} else {
+			while ( ppValue != NULL && *ppValue != NULL && rc == LDAP_SUCCESS ) {
+				pTmpBV = (struct berval *)slapi_ch_malloc(sizeof(struct berval));
+				if ( pTmpBV == NULL) {
+					rc = LDAP_NO_MEMORY;
+				} else {
+					pTmpBV->bv_val = slapi_ch_strdup(*ppValue);
+					if ( pTmpBV->bv_val == NULL ) {
+						rc = LDAP_NO_MEMORY;
+					} else {
+						pTmpBV->bv_len = strlen(*ppValue);
+						*ppNewBV = pTmpBV;
+						ppNewBV++;
+					}
+					ppValue++;
+				}
+			}
+			/* null terminate the array of berval ptrs */
+			*ppNewBV = NULL;
+		}
+	}
+	return( rc );
+}
+
+
+/*
+ * Function : LDAPModToEntry 
+ * convert a dn plus an array of LDAPMod struct ptrs to an entry structure
+ * with a link list of the correspondent attributes.
+ * Return value : LDAP_SUCCESS
+ *                LDAP_NO_MEMORY
+ *                LDAP_OTHER
+*/
+Entry *
+LDAPModToEntry(	char *ldn, 
+				LDAPMod **mods )
+{
+	int				rc=LDAP_SUCCESS;
+	LDAPMod			*pMod;
+	Entry			*pEntry=NULL;
+	int				i,j;
+	struct berval	**ppSaveBV;
+	struct berval	**ppBV;
+	struct berval	*pTmpBV;
+	char			**ppValue;
+
+
+	AttributeDescription *ad;
+	struct berval *bv;
+	const char *text;
+
+    Modifications   *modlist = NULL;
+    Modifications   **modtail = &modlist;
+    Modifications   tmp;
+
+	struct berval dn = { 0, NULL };
+
+	dn.ber_val = slapi_ch_strdup(ldn);
+	dn.ber_len = slapi_ch_strlen(ldn);
+
+	pEntry = (Entry *) ch_calloc( 1, sizeof(Entry) );
+	if ( pEntry == NULL) {
+		rc = LDAP_NO_MEMORY;
+	} else {
+		rc = dnPrettyNormal( NULL, &dn, &e->e_name, &e->e_nname );
+		if( rc != LDAP_SUCCESS ) { 
+#ifdef NEW_LOGGING
+			LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
+				"LDAPModToEntry: invalid dn (%s)\n", dn.bv_val ));
+#else
+			Debug( LDAP_DEBUG_ANY, "LDAPModToEntry: invalid dn (%s)\n", dn.bv_val, 0, 0 ); 
+#endif
+			rc = LDAP_INVALID_DN_SYNTAX;
+		}
+	}
+	if ( rc == LDAP_SUCCESS ) {
+		for ( i=0, pMod=mods[0]; rc == LDAP_SUCCESS && pMod != NULL; pMod=mods[++i]) {
+			Modifications *mod;
+			if ( (pMod->mod_op & LDAP_MOD_BVALUES) != 0 ) {
+				/* attr values are in berval format */
+				/* convert an array of pointers to bervals to an array of bervals */
+				rc = bvptr2obj(pMod->mod_bvalues, &bv);
+				if (rc != LDAP_SUCCESS) break;
+				tmp.sml_type = pMod->mod_type;
+				tmp.sml_bvalues = bv;
+		
+				mod  = (Modifications *) ch_malloc( sizeof(Modifications) );
+
+				mod->sml_op = LDAP_MOD_ADD;
+				mod->sml_next = NULL;
+				mod->sml_desc = NULL;
+				mod->sml_type = tmp.sml_type;
+				mod->sml_bvalues = tmp.sml_bvalues;
+
+				*modtail = mod;
+				modtail = &mod->sml_next;
+
+			} else {
+            	/* attr values are in string format, need to be converted */
+				/* to an array of bervals */ 
+				if ( pMod->mod_values == NULL ) {
+					rc = LDAP_OTHER;
+				} else {
+					rc = ValuesToBValues( pMod->mod_values, &ppBV );
+					if (rc != LDAP_SUCCESS) break;
+					rc = bvptr2obj(ppBV, &bv);
+					if (rc != LDAP_SUCCESS) break;
+					tmp.sml_type = pMod->mod_type;
+					tmp.sml_bvalues = bv;
+		
+					mod  = (Modifications *) ch_malloc( sizeof(Modifications) );
+
+					mod->sml_op = LDAP_MOD_ADD;
+					mod->sml_next = NULL;
+					mod->sml_desc = NULL;
+					mod->sml_type = tmp.sml_type;
+					mod->sml_bvalues = tmp.sml_bvalues;
+
+					*modtail = mod;
+					modtail = &mod->sml_next;
+
+
+					if ( ppBV != NULL ) {
+						ber_bvecfree( ppBV );
+					}
+				}
+			}
+		} /* for each LDAPMod */
+	}
+
+    if( e->e_nname.bv_len == 0 ) 
+		rc = LDAP_ALREADY_EXISTS;
+
+	/* check if ManageDsaIt control is set  */
+	if ( rc = slapi_control_present( controls, LDAP_MANAGEDSAIT_OID, NULL, &isCritical)){
+		manageDsaIt = 1; /* turn off referral */
+	}
+
+	if ( rc == LDAP_SUCCESS ) {
+		be = select_backend(&bv, manageDsaIt, 0);
+		if ( be == NULL ) rc =  LDAP_PARTIAL_RESULTS;
+	}
+
+	if ( rc == LDAP_SUCCESS ) {
+		rc = backend_check_restrictions( be, conn, op, NULL, &text ) ;
+	}
+
+	if ( rc == LDAP_SUCCESS ) {
+		rc = backend_check_referrals( be, conn, op, &pdn, &ndn );
+	}
+
+
+	if ( rc != LDAP_SUCCESS ) {
+		if ( pEntry != NULL ) {
+			slapi_entry_free( pEntry );
+		}
+		pEntry = NULL;
+	}
+    return( pEntry );
+}
+
+/*xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
+
+Slapi_PBlock * 
+slapi_add_entry_internal(	Slapi_Entry *e, 
+							LDAPControl **controls, 
+							int log_changes) 
+{
+	int				rc=LDAP_SUCCESS, i;
+	Backend			*be;
+	Connection		*pConn=NULL;
+	Operation		*op;
+	Slapi_PBlock	*pPB=NULL, *pSavePB=NULL;
+	char			*pDn=NULL;
+	int				manageDsaIt = 0; /* referral is on */
+	int				isCritical;
+	struct berval	bv;
+	
+	/* check if ManageDsaIt control is set  */
+	if (slapi_control_present( controls, LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical)) {
+		 manageDsaIt = 1; /* turn off referral */
+	}
+
+	pConn = fakeConnection(NULL, LDAP_REQ_ADD);
+	if ( pConn == NULL ) {
+		rc = LDAP_NO_MEMORY;
+	} else { 
+		pPB = (Slapi_PBlock *)pConn->c_pending_ops.stqh_first->o_pb;
+		if (e == NULL) {
+			rc =  LDAP_OPERATIONS_ERROR;
+		} else {
+			if ( rc == LDAP_SUCCESS ) {
+				be = select_backend(&e->e_nname, manageDsaIt, 0);
+				if ( be == NULL ) {
+					rc = LDAP_PARTIAL_RESULTS;
+				} else if ( be->be_add == NULL) { 
+					rc = LDAP_UNWILLING_TO_PERFORM;
+				} else {
+					op = (Operation *)pConn->c_pending_ops.stqh_first;
+					op->o_ctrls = controls;
+					rc = (*be->be_add)( be, pConn, op, e );
+					if (rc == LDAP_SUCCESS)
+						Debug (LDAP_DEBUG_TRACE, " backend routine successful \n", 0, 0, 0);
+					else
+						Debug (LDAP_DEBUG_TRACE, " backend routine NOT successful \n", 0, 0, 0);
+				}
+			}
+		}
+	}
+	if ( pPB != NULL ) 
+		slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );   
+	if ( pDn != NULL )
+		slapi_ch_free( pDn );
+	if (bv.bv_val != NULL)
+		slapi_ch_free(bv.bv_val);
+	if ( pConn != NULL ) {
+		if ( pConn->c_dn.bv_val ) 
+			slapi_ch_free( pConn->c_dn.bv_val );
+		if ( pConn->c_pending_ops.stqh_first->o_dn.bv_val )
+			slapi_ch_free( pConn->c_pending_ops.stqh_first->o_dn.bv_val );
+		if ( pConn->c_pending_ops.stqh_first )
+			slapi_ch_free( pConn->c_pending_ops.stqh_first);
+		if (pConn->c_original_dn)
+			slapi_ch_free(pConn->c_original_dn); 
+		pSavePB = pPB;
+		free( pConn );
+	}
+	return( pSavePB );
+}
+
+
+
+Slapi_PBlock *
+slapi_add_internal(	char *dn, 
+					LDAPMod **mods, 
+					LDAPControl **controls, 
+					int log_changes  ) 
+{
+	LDAPMod			*pMod=NULL;
+	Slapi_PBlock	*pb=NULL;
+	Entry			*pEntry=NULL;
+	int				i, rc=LDAP_SUCCESS;
+
+
+	if(mods == NULL || *mods == NULL || dn == NULL || *dn == NULL) 
+		rc = LDAP_OPERATIONS_ERROR ;
+
+	if (rc == LDAP_SUCCESS) {
+		for (i=0, pMod=mods[0]; pMod != NULL; pMod=mods[++i] ) {
+			if ((pMod->mod_op & ~LDAP_MOD_BVALUES) != LDAP_MOD_ADD) {
+				rc = LDAP_OTHER;
+				break;
+			}
+		}
+	}
+
+	if ( rc == LDAP_SUCCESS ) {
+		if((pEntry = LDAPModToEntry( dn, mods )) == NULL) {
+			rc = LDAP_OTHER;
+		}
+	}
+
+	if(rc != LDAP_SUCCESS) {
+		pb = slapi_pblock_new();
+		slapi_pblock_set(pb, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
+	} else {
+		pb = slapi_add_entry_internal(pEntry, controls, log_changes);
+	}
+
+	if(pEntry) 
+		slapi_entry_free(pEntry);
+
+	return(pb);
+}
+
+
+/*dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd*/
+/* Function : slapi_modify_internal
+ *
+ * Description : Plugin functions call this routine to modify an entry in the backend directly
+ * Return values : LDAP_SUCCESS
+ *                 LDAP_OPERAITONS_ERROR
+ *                 LDAP_NO_MEMORY
+ *                 LDAP_OTHER
+ *                 LDAP_UNWILLING_TO_PERFORM
+*/
+Slapi_PBlock *
+slapi_modify_internal( char *dn, LDAPMod **mods, LDAPControl **controls, int log_change)
+{
+	int				rc=LDAP_SUCCESS;
+	int				i;
+	int				dnBadChar;
+	LDAPMod			*pMod;
+	LDAPMod			*pNewMod;
+	LDAPMod			*pTmpMod;
+	LDAPMod			*pSaveMod;
+	LDAPMod			*pModList=NULL;
+	Backend			*be;
+	Slapi_PBlock	*pPB=NULL;
+	Slapi_PBlock	*pSavePB=NULL;
+	Connection		*pConn=NULL;
+
+	int				manageDsaIt = 0;
+	int				isCritical;
+	struct berval	bv;
+	struct berval	*pbv;
+	AttributeDescription *ad;
+	const char		*text;
+	Operation		*op;
+	Modifications	*modlist = NULL;
+	Modifications	**modtail = &modlist;
+	struct berval pdn = { 0, NULL };
+	struct berval ndn = { 0, NULL };
+
+
+
+	pConn = fakeConnection( NULL,  LDAP_REQ_MODIFY );
+	if ( pConn == NULL ) {
+		rc = LDAP_NO_MEMORY;
+	} else {
+		pPB = (Slapi_PBlock *)pConn->c_pending_ops.stqh_first->o_pb;
+		if ( dn == NULL || mods == NULL || *mods == NULL ) {
+			rc = LDAP_OPERATIONS_ERROR; 
+		}
+	}
+	if ( rc == LDAP_SUCCESS ) {
+		dn_normalize( dn );
+
+		Debug(LDAP_DEBUG_TRACE,"slapi modifying object %s.\n", dn, 0, 0);
+		rc = dn_check(dn, &dnBadChar);
+		if ( rc == LDAP_SUCCESS ) {
+
+			/* We could be serving multiple database backends.  Select the
+			 * appropriate one, or send a referral to our "referral server"
+			 * if we don't hold it. 
+			 */
+
+			/* check if ManageDsaIt control is set  */
+			if ( slapi_control_present( controls,
+				 LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical ) ) {
+					manageDsaIt = 1; /* turn off referral */
+			}
+			bv.bv_val = strdup(dn);
+			bv.bv_len = strlen(dn);
+			be = select_backend(&bv, manageDsaIt, 0);
+			if ( be == NULL )  {
+				rc =  LDAP_PARTIAL_RESULTS;
+			} else if ( be->be_modify == NULL ) {
+				rc = LDAP_UNWILLING_TO_PERFORM;
+			}
+		}
+	}
+	if ( rc == LDAP_SUCCESS ) {
+		for ( i=0, pMod=mods[0]; pMod != NULL; pMod=mods[++i] ) {
+			if ( (pMod->mod_op & LDAP_MOD_BVALUES) != 0 ) {
+            	/* attr values are in berval format, merge them with the Entry's attr list */
+				rc = duplicateBVMod( pMod, &pNewMod );
+			} else {
+            	pNewMod = (LDAPMod *)slapi_ch_malloc(sizeof(LDAPMod));
+            	if ( pNewMod == NULL ) {
+					rc = LDAP_NO_MEMORY;
+				} else {
+					memset( pNewMod, '\0', sizeof(LDAPMod) );
+					pNewMod->mod_op = pMod->mod_op | LDAP_MOD_BVALUES;
+					pNewMod->mod_type = slapi_ch_strdup( pMod->mod_type );
+					if ( pNewMod->mod_type == NULL ) {
+						rc = LDAP_NO_MEMORY;
+					} else {
+						if ( (pMod->mod_op & ~LDAP_MOD_BVALUES) == LDAP_MOD_DELETE ) {
+							rc = ValuesToBValues( pMod->mod_values, &(pNewMod->mod_bvalues) );
+						} else {
+							if ( pMod->mod_values == NULL ) {
+								Debug(LDAP_DEBUG_TRACE,
+								 "slapi_modify_internal:mod_values is null\n",0, 0, 0);
+                      			rc = LDAP_OTHER;
+							} else {
+								rc = ValuesToBValues( pMod->mod_values, 
+													  &(pNewMod->mod_bvalues) );
+							}
+						}
+					}
+            	}
+			}
+			if ( rc == LDAP_SUCCESS ) {
+				/* add the new mod to the end of mod list */
+				if ( pModList == NULL ) {
+					pModList = pNewMod;
+				} else {
+					pTmpMod = pModList;
+					while ( pTmpMod != NULL ) {
+						pSaveMod = pTmpMod;
+						pTmpMod = pTmpMod->mod_next;
+					}
+					pSaveMod->mod_next = pNewMod;
+				}
+			}
+		}  /* for each LDAPMod */
+	}
+
+	if ( rc == LDAP_SUCCESS ) {
+		/* convert LDAPModList to Modification list */
+		pTmpMod = pModList;
+		while (pTmpMod != NULL) {
+			Modifications *mod;
+			mod = (Modifications *) ch_malloc( sizeof(Modifications) );
+			mod->sml_type.bv_val = ch_strdup(pTmpMod->mod_type);
+			mod->sml_type.bv_len = strlen(pTmpMod->mod_type);
+			mod->sml_op = pTmpMod->mod_op;
+			pbv = NULL;
+			rc = bvptr2obj(pTmpMod->mod_bvalues, &pbv);
+			mod->sml_bvalues = pbv;
+			ad = NULL;
+			rc = slap_str2ad(pTmpMod->mod_type, &ad, &text );
+			mod->sml_desc = ad;
+			*modtail = mod;
+			modtail = &mod->sml_next;
+			pTmpMod = pTmpMod->mod_next;
+		}
+		*modtail = NULL;
+	}
+
+   if ( rc == LDAP_SUCCESS ) {
+		op = (Operation *)pConn->c_pending_ops.stqh_first;
+		op->o_ctrls = controls;
+		Debug (LDAP_DEBUG_TRACE, "Calling backend routine \n", 0, 0, 0);
+		pdn.bv_val = ch_strdup(dn);
+		pdn.bv_len = strlen(dn);
+		ndn.bv_val = ch_strdup(dn);
+		ndn.bv_len = strlen(dn);
+		rc = (*be->be_modify)( be, pConn, op, &pdn, &ndn, modlist );
+		if (rc == LDAP_SUCCESS)
+             Debug (LDAP_DEBUG_TRACE, " backend routine successful \n", 0, 0, 0);
+		else
+			Debug (LDAP_DEBUG_TRACE, " backend routine NOT successful \n", 0, 0, 0);
+
+	} else { 
+		rc = LDAP_OPERATIONS_ERROR;
+	}
+
+   if ( pPB != NULL ) {
+      slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
+   }
+   if (pModList != NULL)  {
+         freeModList( pModList ); 
+   }
+   if ( pConn != NULL ) {
+      if ( pConn->c_dn.bv_val )
+         slapi_ch_free( pConn->c_dn.bv_val );
+      if ( pConn->c_original_dn )
+         slapi_ch_free( pConn->c_original_dn ); 
+      if ( pConn->c_pending_ops.stqh_first->o_dn.bv_val )
+         slapi_ch_free( pConn->c_pending_ops.stqh_first->o_dn.bv_val);
+      if ( pConn->c_pending_ops.stqh_first )
+         slapi_ch_free( pConn->c_pending_ops.stqh_first );
+      pSavePB = pPB;
+      free( pConn );
+   }
+   return( pSavePB );
+}
+
+
+/* Function : slapi_modrdn_internal
+ *
+ * Description : Plugin functions call this routine to modify the rdn 
+ *				 of an entry in the backend directly
+ * Return values : LDAP_SUCCESS
+ *                 LDAP_OPERAITONS_ERROR
+ *                 LDAP_NO_MEMORY
+ *                 LDAP_OTHER
+ *                 LDAP_UNWILLING_TO_PERFORM
+*/
+Slapi_PBlock *
+slapi_modrdn_internal(	char *olddn, 
+						char *newrdn, 
+						int deloldrdn, 
+						LDAPControl **controls, 
+						int log_change)
+{
+
+	int				rc=LDAP_SUCCESS;
+	int				dnBadChar;
+	Backend			*be;
+	char			*pDn=NULL;
+	Slapi_PBlock	*pPB=NULL;
+	Slapi_PBlock	*pSavePB=NULL;
+	Connection		*pConn=NULL;
+
+	int				manageDsaIt = 0;
+    int				isCritical;
+    struct berval	bv  = { 0, NULL };
+	Operation       *op;
+
+	struct berval dn = { 0, NULL };
+	struct berval ndn = { 0, NULL };
+	struct berval pdn = { 0, NULL };
+
+	struct berval newrdnO = { 0, NULL };
+	struct berval nnewrdnO = { 0, NULL };
+	struct berval pnewrdnO = { 0, NULL };
+
+	struct berval *nnewS = NULL;
+	struct berval *pnewS = NULL;
+
+	
+	dn.bv_val = ch_strdup(olddn);
+	if (dn.bv_val == NULL) {
+		rc = LDAP_NO_MEMORY;
+	} else {
+		dn.bv_len = strlen(olddn);
+	}
+
+	if (rc == LDAP_SUCCESS) {
+		newrdnO.bv_val = ch_strdup(newrdn);
+		if (newrdnO.bv_val == NULL) {
+			rc = LDAP_NO_MEMORY;
+		} else {
+			newrdnO.bv_len = strlen(newrdn);
+		}
+	} 
+
+	if (rc == LDAP_SUCCESS) {
+		rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn );
+	}
+
+	if (rc == LDAP_SUCCESS) {
+		rc = dnPrettyNormal( NULL, &newrdnO, &pnewrdnO, &nnewrdnO );
+	}
+		
+	if ( rc == LDAP_SUCCESS ) {
+		pConn = fakeConnection(NULL,  LDAP_REQ_MODRDN );
+	} 
+
+	if ( pConn == NULL ) {
+		rc = LDAP_NO_MEMORY;
+	} else {
+		pPB = (Slapi_PBlock *)pConn->c_pending_ops.stqh_first->o_pb;
+		if ( olddn == NULL || newrdn == NULL ) {
+			rc = LDAP_OPERATIONS_ERROR;
+		}
+	}
+	if ( rc == LDAP_SUCCESS ) {
+		Debug(LDAP_DEBUG_TRACE,"slapi modify rdn %s new RDN: %s.\n", olddn, newrdn, 0);
+		rc = dn_check(olddn, &dnBadChar);
+	}
+
+	if ( rc == LDAP_SUCCESS ) {
+
+		/* We could be serving multiple database backends.  Select the
+		 * appropriate one, or send a referral to our "referral server"
+		 * if we don't hold it. */
+
+		op = (Operation *)pConn->c_pending_ops.stqh_first;
+		op->o_ctrls = controls;
+
+		/* check if ManageDsaIt control is set  */
+		if ( slapi_control_present( controls,
+			 LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical ) ) {
+				manageDsaIt = 1; /* turn off referral */
+		}
+		be = select_backend(&bv, manageDsaIt, 0);
+		if ( be == NULL )  {
+			rc =  LDAP_PARTIAL_RESULTS;
+		}
+	}
+
+	if ( rc == LDAP_SUCCESS ) {
+		if ( be->be_modrdn == NULL ) {
+			rc = LDAP_UNWILLING_TO_PERFORM;
+		} else {
+			Debug (LDAP_DEBUG_TRACE, "Calling backend routine \n", 0, 0, 0);
+			rc = (*be->be_modrdn)( be, pConn, op, &pdn, &ndn,
+                                    &pnewrdnO, &nnewrdnO, deloldrdn, pnewS, nnewS );
+			if (rc == LDAP_SUCCESS)
+				Debug (LDAP_DEBUG_TRACE, " backend routine successful \n", 0, 0, 0);
+			else
+				Debug (LDAP_DEBUG_TRACE, " backend routine NOT successful \n", 0, 0, 0);
+		}
+	}
+
+	if (dn.bv_val)
+		ch_free(dn.bv_val);
+	if (pdn.bv_val)
+		ch_free(pdn.bv_val);
+	if (ndn.bv_val)
+		ch_free(ndn.bv_val);
+	if (newrdnO.bv_val)
+		ch_free(newrdnO.bv_val);
+	if (pnewrdnO.bv_val)
+		ch_free(newrdnO.bv_val);
+	if (nnewrdnO.bv_val)
+		ch_free(newrdnO.bv_val);
+
+	if ( pPB != NULL ) { 
+		slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
+	}
+	if ( pConn != NULL ) {
+		if ( pConn->c_dn.bv_val )
+			slapi_ch_free( pConn->c_dn.bv_val );
+		if (pConn->c_original_dn)
+			slapi_ch_free(pConn->c_original_dn);
+		if ( pConn->c_pending_ops.stqh_first->o_dn.bv_val )
+			slapi_ch_free( pConn->c_pending_ops.stqh_first->o_dn.bv_val );
+		if ( pConn->c_pending_ops.stqh_first )
+			slapi_ch_free( pConn->c_pending_ops.stqh_first );
+		pSavePB = pPB;
+		free( pConn );
+	}
+	return( pSavePB );
+}
+
+Slapi_PBlock * 
+slapi_search_internal( char *base, int scope, char *filStr, 
+					   LDAPControl **controls, char **attrs, int attrsonly ) 
+{
+	return slapi_search_internal_bind(NULL,base,scope,filStr,controls, attrs,attrsonly);
+}
+
+Slapi_PBlock *
+slapi_search_internal_bind( char *bindDN, char *b, int scope, char *filStr, 
+							 LDAPControl **controls, char **attrs, int attrsonly ) 
+{	
+	Slapi_PBlock	*ptr;		
+	Connection		*c;
+	Backend			*be;
+	Filter			*filter=NULL;
+	int				i, deref=0, sizelimit=-1, timelimit=-1, rc, dnCheckJunk=0;
+	int				manageDsaIt = 0; 
+	int				isCritical;
+	struct berval	bv;
+	Operation		*op;
+
+	struct berval base = { 0, NULL };
+	struct berval pbase = { 0, NULL };
+	struct berval nbase = { 0, NULL };
+	AttributeName   *an;
+	const char      *text;
+	struct berval   fstr = { 0, NULL };
+
+
+	
+	c=fakeConnection(bindDN,LDAP_REQ_SEARCH);
+
+	if ( c == NULL ) { 
+		rc = LDAP_NO_MEMORY;
+	} else {
+		ptr = (Slapi_PBlock *)c->c_pending_ops.stqh_first->o_pb;
+    }
+
+	/* check if ManageDsaIt control is set  */
+	if ( rc = slapi_control_present( controls, 
+									 LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical ) ) {
+		manageDsaIt = 1; /* turn off referral */
+	}
+	if ( scope != LDAP_SCOPE_BASE && scope != LDAP_SCOPE_ONELEVEL
+									&& scope != LDAP_SCOPE_SUBTREE ) {
+		slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)LDAP_PROTOCOL_ERROR);
+		return ptr;
+	}
+
+	dn_normalize( b );
+	rc=dn_check(b, &dnCheckJunk);
+	if(rc != LDAP_SUCCESS) {
+		slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)rc);
+		return ptr;
+	}
+
+	if ( attrs != NULL ) {
+		for ( i = 0; attrs[i] != NULL; i++ )
+			attr_normalize( attrs[i] );
+	}
+	if((filter=slapi_str2filter(filStr)) == NULL) {
+		slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)LDAP_PROTOCOL_ERROR);
+		return ptr;
+	}
+	bv.bv_val = ch_strdup(b);
+	bv.bv_len = strlen(b);
+	/* check if ManageDsaIt control is set  */
+	if ( slapi_control_present( controls,
+		LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical ) ) {
+		manageDsaIt = 1; /* turn off referral */
+	}
+
+	if ((be = select_backend( &bv, manageDsaIt, 0 )) == NULL) {
+                if ( manageDsaIt == 1 ) { /* referral turned off */
+                        slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)LDAP_NO_SUCH_OBJECT);
+                } else {
+                        slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)LDAP_PARTIAL_RESULTS);
+                }
+		return ptr;
+	} else if ( be->be_search == NULL ) {
+		slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)LDAP_UNWILLING_TO_PERFORM);
+		return ptr;
+	} else {
+
+		base.bv_val = ch_strdup(b);
+		base.bv_len = strlen(b);
+		rc = dnPrettyNormal( NULL, &base, &pbase, &nbase );
+		for (i = 0; attrs[i] != 0; i++) {
+			an[i].an_desc = NULL;
+			an[i].an_name.bv_val = ch_strdup(attrs[i]);
+			an[i].an_name.bv_len = strlen(attrs[i]);
+			slap_bv2ad(&an[i].an_name, &an[i].an_desc, &text);
+		}
+		fstr.bv_val = ch_strdup(filStr);
+		fstr.bv_len = strlen(filStr);
+		rc = (*be->be_search)( be, c, op, &pbase, &nbase, scope, deref, 
+					sizelimit, timelimit, filter, &fstr, an, attrsonly );
+	} 
+	slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)rc); 
+        if ( c->c_pending_ops.stqh_first ){
+          if(c->c_dn.bv_val)
+            slapi_ch_free(c->c_dn.bv_val);
+          if (c->c_original_dn)
+            slapi_ch_free(c->c_original_dn); 
+          if(c->c_pending_ops.stqh_first->o_dn.bv_val)
+            slapi_ch_free(c->c_pending_ops.stqh_first->o_dn.bv_val);
+          slapi_ch_free( c->c_pending_ops.stqh_first );
+        }
+	slapi_ch_free((void **)c);
+	if (filter) 
+		slapi_filter_free(filter,1);
+	return ptr;	
+}
+
+/*
+ Function : slapi_get_supported_extended_ops
+ Description : This function returns a pointer points to an array of Null terminated char pointers.
+               Each char pointer points to an oid of an extended operation.
+               If there is no defined extended operaitons, this routine returns NULL. 
+ Input : none
+ Output : pointer to an null terminated char pointer array or null.
+ Notes: The caller of this routine needs to free the retuned array pointer, but
+        should not free the pointers inside the array.
+*/
+char
+**slapi_get_supported_extended_ops(void)
+{
+
+	ExtendedOp   *pTmpExtOp;
+	int          numExtOps = 0;
+	int          i=0;
+	char         **ppExtOpOID = NULL;
+
+	if ( pGExtendedOps != NULL ) {
+		pTmpExtOp = pGExtendedOps;
+			while ( pTmpExtOp != NULL ) {
+				numExtOps++;
+				pTmpExtOp = pTmpExtOp->ext_next;
+			}
+
+		if ( numExtOps > 0 ) {
+			ppExtOpOID = (char **)slapi_ch_malloc( (numExtOps+1) * sizeof(char *) );
+			if ( ppExtOpOID != NULL ) {
+				pTmpExtOp = pGExtendedOps;
+				while ( pTmpExtOp != NULL ) {
+					ppExtOpOID[i] = pTmpExtOp->ext_oid;
+					i++;
+					pTmpExtOp = pTmpExtOp->ext_next;
+				}
+				ppExtOpOID[i] = NULL;
+			}
+		}
+	}
+
+	return( ppExtOpOID );
+}
+
+Slapi_PBlock *
+slapi_simple_bind_internal( char *d, struct berval *cred, int method, int version)
+{
+
+	int				rc=LDAP_SUCCESS;
+	Connection		*pConn=NULL;
+	Backend			*be;
+	Slapi_PBlock	*pPB=NULL;
+	int				dnBadChar;
+
+	int             isCritical;
+	struct berval   bv;
+	struct berval 	dn = { 0, NULL };
+	struct berval 	pdn = { 0, NULL };
+	struct berval 	ndn = { 0, NULL };
+	Operation		*op;
+
+
+	pConn = fakeConnection(NULL, LDAP_REQ_BIND );
+
+	if ( pConn == NULL ) {
+		rc = LDAP_NO_MEMORY;
+	} else {
+		pPB = (Slapi_PBlock *)pConn->c_pending_ops.stqh_first->o_pb;
+		pConn->c_version = version;
+		op = (Operation *)pConn->c_pending_ops.stqh_first;
+	}
+
+	if ( d == NULL ) {
+		rc = LDAP_OPERATIONS_ERROR;
+	} else {
+		dn.bv_val = ch_strdup (d);
+		dn.bv_len = strlen(d);
+		rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn );
+	}
+
+	if ( rc == LDAP_SUCCESS ) {
+		be = select_backend(&ndn, 0, 0 );
+		if ( be == NULL )  {
+			rc =  LDAP_PARTIAL_RESULTS;
+		} else if ( be->be_bind == NULL  ) {
+			rc = LDAP_UNWILLING_TO_PERFORM;
+		}
+	}
+
+	rc = (*be->be_bind)( be, pConn, op,
+					&pdn, &ndn, method, cred, NULL );
+
+	if (rc == LDAP_SUCCESS) {
+		pConn->c_version = version;
+		pConn->c_dn.bv_val = strdup( d );
+		pConn->c_dn.bv_len = strlen( d );
+		if (pConn->c_dn.bv_val == NULL) {
+			rc = LDAP_NO_MEMORY;
+			Debug (LDAP_DEBUG_TRACE, " backend routine successful, but has no more memory \n",0, 0, 0);
+		} 
+		Debug (LDAP_DEBUG_TRACE, " backend routine NOT successful \n", 0, 0, 0);
+	}
+
+	if ( pPB != NULL )
+       slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
+
+   return(pPB);
+
+}
+
+#endif
diff --git a/servers/slapd/slapi/slapi_ops.h b/servers/slapd/slapi/slapi_ops.h
new file mode 100644
index 0000000000..26adf35aa8
--- /dev/null
+++ b/servers/slapd/slapi/slapi_ops.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ * (C) Copyright IBM Corp. 1997,2002
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is 
+ * given to IBM Corporation. This software is provided ``as is'' 
+ * without express or implied warranty.
+ */
+
+#ifndef SLAPI_OPS_H
+#define SLAPI_OPS_H
+
+Slapi_PBlock *slapi_search_internal( char *base, int scope, char *filter, 
+	LDAPControl **controls, char **attrs, int attrsonly );
+Slapi_PBlock *slapi_search_internal_bind( char *bindDN, char *base, int scope, char *filter, 
+	LDAPControl **controls, char **attrs, int attrsonly ); /* d58508 */
+Slapi_PBlock *slapi_modify_internal( char *dn, LDAPMod **mods,
+        LDAPControl **controls, int log_change );
+Slapi_PBlock *slapi_add_entry_internal( Slapi_Entry * e, LDAPControl **controls, int log_change );
+Slapi_PBlock *slapi_add_internal( char * dn, LDAPMod **attrs, LDAPControl **controls, int log_changes );
+Slapi_PBlock *slapi_add_entry_internal( Slapi_Entry * e, LDAPControl **controls, int log_change );
+Slapi_PBlock *slapi_delete_internal( char * dn,  LDAPControl **controls, int log_change );
+Slapi_PBlock *slapi_modrdn_internal( char * olddn, char * newrdn, int deloldrdn, LDAPControl **controls, int log_change);
+/*
+Slapi_PBlock *slapi_modrdn_internal( char * olddn, char * newrdn, char *newParent, int deloldrdn, LDAPControl **controls, int log_change);
+*/
+char **slapi_get_supported_extended_ops(void);
+int duplicateBVMod( LDAPMod *pMod, LDAPMod **ppNewMod );
+
+#endif /* SLAPI_OPS_H */
+
diff --git a/servers/slapd/slapi/slapi_pblock.c b/servers/slapd/slapi/slapi_pblock.c
new file mode 100644
index 0000000000..03edd7ce4d
--- /dev/null
+++ b/servers/slapd/slapi/slapi_pblock.c
@@ -0,0 +1,436 @@
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ * (C) Copyright IBM Corp. 1997,2002
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is 
+ * given to IBM Corporation. This software is provided ``as is'' 
+ * without express or implied warranty.
+ */
+
+#include "portable.h"
+#include "slapi_common.h"
+#include <slap.h>
+#include <slapi.h>
+
+static int 
+isOkNetscapeParam( int param ) 
+{
+	switch ( param ) {
+	case SLAPI_BACKEND:
+	case SLAPI_CONNECTION:
+	case SLAPI_OPERATION:
+	case SLAPI_REQUESTOR_ISROOT:
+	case SLAPI_BE_MONITORDN:
+	case SLAPI_BE_TYPE:
+	case SLAPI_BE_READONLY:
+	case SLAPI_BE_LASTMOD:
+	case SLAPI_CONN_ID:
+	case SLAPI_OPINITIATED_TIME:
+	case SLAPI_REQUESTOR_DN:
+	case SLAPI_REQUESTOR_ISUPDATEDN:
+	case SLAPI_CONN_DN:
+	case SLAPI_CONN_AUTHTYPE:
+	case SLAPI_IBM_CONN_DN_ALT:
+	case SLAPI_IBM_CONN_DN_ORIG:
+	case SLAPI_IBM_GSSAPI_CONTEXT:
+	case SLAPI_PLUGIN:
+	case SLAPI_PLUGIN_PRIVATE:
+	case SLAPI_PLUGIN_TYPE:
+	case SLAPI_PLUGIN_ARGV:
+	case SLAPI_PLUGIN_ARGC:
+	case SLAPI_PLUGIN_VERSION:
+	case SLAPI_PLUGIN_OPRETURN:
+	case SLAPI_PLUGIN_OBJECT:
+	case SLAPI_PLUGIN_DESTROY_FN:
+	case SLAPI_PLUGIN_DESCRIPTION:
+	case SLAPI_PLUGIN_INTOP_RESULT:
+	case SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES:
+	case SLAPI_PLUGIN_INTOP_SEARCH_REFERRALS:
+	case SLAPI_PLUGIN_DB_BIND_FN:
+	case SLAPI_PLUGIN_DB_UNBIND_FN:
+	case SLAPI_PLUGIN_DB_SEARCH_FN:
+	case SLAPI_PLUGIN_DB_COMPARE_FN:
+	case SLAPI_PLUGIN_DB_MODIFY_FN:
+	case SLAPI_PLUGIN_DB_MODRDN_FN:
+	case SLAPI_PLUGIN_DB_ADD_FN:
+	case SLAPI_PLUGIN_DB_DELETE_FN:
+	case SLAPI_PLUGIN_DB_ABANDON_FN:
+	case SLAPI_PLUGIN_DB_CONFIG_FN:
+	case SLAPI_PLUGIN_CLOSE_FN:
+	case SLAPI_PLUGIN_DB_FLUSH_FN:
+	case SLAPI_PLUGIN_START_FN:
+	case SLAPI_PLUGIN_DB_SEQ_FN:
+	case SLAPI_PLUGIN_DB_ENTRY_FN:
+	case SLAPI_PLUGIN_DB_REFERRAL_FN:
+	case SLAPI_PLUGIN_DB_RESULT_FN:
+	case SLAPI_PLUGIN_DB_LDIF2DB_FN:
+	case SLAPI_PLUGIN_DB_DB2LDIF_FN:
+	case SLAPI_PLUGIN_DB_BEGIN_FN:
+	case SLAPI_PLUGIN_DB_COMMIT_FN:
+	case SLAPI_PLUGIN_DB_ABORT_FN:
+	case SLAPI_PLUGIN_DB_ARCHIVE2DB_FN:
+	case SLAPI_PLUGIN_DB_DB2ARCHIVE_FN:
+	case SLAPI_PLUGIN_DB_NEXT_SEARCH_ENTRY_FN:
+	case SLAPI_PLUGIN_DB_FREE_RESULT_SET_FN:
+	case SLAPI_PLUGIN_DB_SIZE_FN:
+	case SLAPI_PLUGIN_DB_TEST_FN:
+	case SLAPI_PLUGIN_DB_NO_ACL:
+	case SLAPI_PLUGIN_EXT_OP_FN:
+	case SLAPI_PLUGIN_EXT_OP_OIDLIST:
+	case SLAPI_PLUGIN_PRE_BIND_FN:
+	case SLAPI_PLUGIN_PRE_UNBIND_FN:
+	case SLAPI_PLUGIN_PRE_SEARCH_FN:
+	case SLAPI_PLUGIN_PRE_COMPARE_FN:
+	case SLAPI_PLUGIN_PRE_MODIFY_FN:
+	case SLAPI_PLUGIN_PRE_MODRDN_FN:
+	case SLAPI_PLUGIN_PRE_ADD_FN:
+	case SLAPI_PLUGIN_PRE_DELETE_FN:
+	case SLAPI_PLUGIN_PRE_ABANDON_FN:
+	case SLAPI_PLUGIN_PRE_ENTRY_FN:
+	case SLAPI_PLUGIN_PRE_REFERRAL_FN:
+	case SLAPI_PLUGIN_PRE_RESULT_FN:
+	case SLAPI_PLUGIN_POST_BIND_FN:
+	case SLAPI_PLUGIN_POST_UNBIND_FN:
+	case SLAPI_PLUGIN_POST_SEARCH_FN:
+	case SLAPI_PLUGIN_POST_COMPARE_FN:
+	case SLAPI_PLUGIN_POST_MODIFY_FN:
+	case SLAPI_PLUGIN_POST_MODRDN_FN:
+	case SLAPI_PLUGIN_POST_ADD_FN:
+	case SLAPI_PLUGIN_POST_DELETE_FN:
+	case SLAPI_PLUGIN_POST_ABANDON_FN:
+	case SLAPI_PLUGIN_POST_ENTRY_FN:
+	case SLAPI_PLUGIN_POST_REFERRAL_FN:
+	case SLAPI_PLUGIN_POST_RESULT_FN:
+	case SLAPI_PLUGIN_MR_FILTER_CREATE_FN:
+	case SLAPI_PLUGIN_MR_INDEXER_CREATE_FN:
+	case SLAPI_PLUGIN_MR_FILTER_MATCH_FN:
+	case SLAPI_PLUGIN_MR_FILTER_INDEX_FN:
+	case SLAPI_PLUGIN_MR_FILTER_RESET_FN:
+	case SLAPI_PLUGIN_MR_INDEX_FN:
+	case SLAPI_PLUGIN_MR_OID:
+	case SLAPI_PLUGIN_MR_TYPE:
+	case SLAPI_PLUGIN_MR_VALUE:
+	case SLAPI_PLUGIN_MR_VALUES:
+	case SLAPI_PLUGIN_MR_KEYS:
+	case SLAPI_PLUGIN_MR_FILTER_REUSABLE:
+	case SLAPI_PLUGIN_MR_QUERY_OPERATOR:
+	case SLAPI_PLUGIN_MR_USAGE:
+	case SLAPI_OP_LESS:
+	case SLAPI_OP_LESS_OR_EQUAL:
+	case SLAPI_PLUGIN_MR_USAGE_INDEX:
+	case SLAPI_PLUGIN_SYNTAX_FILTER_AVA:
+	case SLAPI_PLUGIN_SYNTAX_FILTER_SUB:
+	case SLAPI_PLUGIN_SYNTAX_VALUES2KEYS:
+	case SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_AVA:
+	case SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_SUB:
+	case SLAPI_PLUGIN_SYNTAX_NAMES:
+	case SLAPI_PLUGIN_SYNTAX_OID:
+	case SLAPI_PLUGIN_SYNTAX_FLAGS:
+	case SLAPI_PLUGIN_SYNTAX_COMPARE:
+	case SLAPI_MANAGEDSAIT:
+	case SLAPI_CONFIG_FILENAME:
+	case SLAPI_CONFIG_LINENO:
+	case SLAPI_CONFIG_ARGC:
+	case SLAPI_CONFIG_ARGV:
+	case SLAPI_TARGET_DN:
+	case SLAPI_REQCONTROLS:
+	case SLAPI_ENTRY_PRE_OP:
+	case SLAPI_ENTRY_POST_OP:
+	case SLAPI_RESCONTROLS:
+	case SLAPI_ADD_RESCONTROL:
+	case SLAPI_ADD_ENTRY:
+	case SLAPI_BIND_METHOD:
+	case SLAPI_BIND_CREDENTIALS:
+	case SLAPI_BIND_SASLMECHANISM:
+	case SLAPI_BIND_RET_SASLCREDS:
+	case SLAPI_COMPARE_TYPE:
+	case SLAPI_COMPARE_VALUE:
+	case SLAPI_MODIFY_MODS:
+	case SLAPI_MODRDN_NEWRDN:
+	case SLAPI_MODRDN_DELOLDRDN:
+	case SLAPI_MODRDN_NEWSUPERIOR:
+	case SLAPI_SEARCH_SCOPE:
+	case SLAPI_SEARCH_DEREF:
+	case SLAPI_SEARCH_SIZELIMIT:
+	case SLAPI_SEARCH_TIMELIMIT:
+	case SLAPI_SEARCH_FILTER:
+	case SLAPI_SEARCH_STRFILTER:
+	case SLAPI_SEARCH_ATTRS:
+	case SLAPI_SEARCH_ATTRSONLY:
+	case SLAPI_ABANDON_MSGID:
+	case SLAPI_SEQ_TYPE:
+	case SLAPI_SEQ_ATTRNAME:
+	case SLAPI_SEQ_VAL:
+	case SLAPI_EXT_OP_REQ_OID:
+	case SLAPI_EXT_OP_REQ_VALUE:
+	case SLAPI_EXT_OP_RET_OID:
+	case SLAPI_EXT_OP_RET_VALUE:
+	case SLAPI_MR_FILTER_ENTRY:
+	case SLAPI_MR_FILTER_TYPE:
+	case SLAPI_MR_FILTER_VALUE:
+	case SLAPI_MR_FILTER_OID:
+	case SLAPI_MR_FILTER_DNATTRS:
+	case SLAPI_LDIF2DB_FILE:
+	case SLAPI_LDIF2DB_REMOVEDUPVALS:
+	case SLAPI_DB2LDIF_PRINTKEY:
+	case SLAPI_PARENT_TXN:
+	case SLAPI_TXN:
+	case SLAPI_SEARCH_RESULT_SET:
+	case SLAPI_SEARCH_RESULT_ENTRY:
+	case SLAPI_NENTRIES:
+	case SLAPI_SEARCH_REFERRALS:
+	case SLAPI_CHANGENUMBER:
+	case SLAPI_LOG_OPERATION:
+	case SLAPI_DBSIZE:
+		return LDAP_SUCCESS;
+	default:
+		return INVALID_PARAM;
+	}
+}
+
+static int
+isValidParam( Slapi_PBlock *pb, int param ) 
+{
+	if ( pb->ckParams == TRUE ) {
+		if ( IBM_RESERVED( param ) ) return LDAP_SUCCESS;
+		if (param == SLAPI_PLUGIN_AUDIT_FN ||
+	     			param == SLAPI_PLUGIN_AUDIT_DATA )
+			return LDAP_SUCCESS;
+		if ( param < LAST_IBM_PARAM ) {
+			return INVALID_PARAM;
+		} else if ( NETSCAPE_RESERVED( param ) ) {
+			return INVALID_PARAM;
+		} else {
+			return isOkNetscapeParam(param);
+		}
+	} else {
+		return LDAP_SUCCESS;
+	}
+}
+
+static void
+Lock( Slapi_PBlock *pb )
+{
+	ldap_pvt_thread_mutex_lock(&pb->pblockMutex);
+}
+
+static void
+unLock( Slapi_PBlock *pb )
+{
+	ldap_pvt_thread_mutex_unlock(&pb->pblockMutex);
+}
+
+static int 
+get( Slapi_PBlock *pb, int param, void **val ) 
+{	
+	int i;
+
+	if ( isValidParam( pb, param ) == INVALID_PARAM ) {
+		return PBLOCK_ERROR;
+	}
+	
+	Lock( pb );
+	
+	*val = NULL;
+	for ( i = 0; i < pb->numParams; i++ ) {
+		if ( pb->curParams[i] == param ) {
+			*val = pb->curVals[i];
+			break;
+	  	}
+	}
+	unLock( pb );	
+	return LDAP_SUCCESS;
+}
+
+static int 
+set( Slapi_PBlock *pb, int param, void *val ) 
+{
+#if defined(LDAP_SLAPI)
+	int i;
+
+	if ( isValidParam( pb, param ) == INVALID_PARAM ) {
+		return PBLOCK_ERROR;
+	}
+
+	Lock( pb );	
+
+	if ( pb->numParams == MAX_PARAMS ) {
+		unLock( pb );
+		return PBLOCK_ERROR; 
+	}
+
+	for( i = 0; i < pb->numParams; i++ ) { 
+		if ( pb->curParams[i] == param ) {
+			break;
+		}
+	}
+
+	if ( i >= pb->numParams ) {
+		pb->curParams[i] = param;
+	  	pb->numParams++;
+	}
+	pb->curVals[i] = val;
+
+	unLock( pb );	
+	return LDAP_SUCCESS;
+#endif /* LDAP_SLAPI */
+	return PBLOCK_ERROR;
+}
+
+static void
+clearPB( Slapi_PBlock *pb ) 
+{
+	pb->numParams = 1;
+}
+
+static void
+checkParams( Slapi_PBlock *pb, int flag ) 
+{
+	pb->ckParams = flag;
+}
+
+static int
+deleteParam( Slapi_PBlock *p, int param ) 
+{
+	int i;
+
+	Lock(p);
+	for ( i = 0; i < p->numParams; i++ ) { 
+		if ( p->curParams[i] == param ) {
+			break;
+		}
+	}
+    
+	if (i >= p->numParams ) {
+		unLock( p );
+		return PBLOCK_ERROR;
+	}
+	if ( p->numParams > 1 ) {
+		p->curParams[i] = p->curParams[p->numParams];
+		p->curVals[i] = p->curVals[p->numParams];
+	}
+	p->numParams--;
+	unLock( p );	
+	return LDAP_SUCCESS;
+}
+
+Slapi_PBlock *
+slapi_pblock_new() 
+{
+#if defined(LDAP_SLAPI)
+	Slapi_PBlock *pb;
+
+	pb = (Slapi_PBlock *) ch_malloc(sizeof(Slapi_PBlock));
+	if ( pb != NULL ) {
+		pb->ckParams = TRUE;
+		ldap_pvt_thread_mutex_init( &pb->pblockMutex );
+		memset( pb->curParams, 0, sizeof(pb->curParams) );
+		memset( pb->curVals, 0, sizeof(pb->curVals) );
+		pb->curParams[0] = SLAPI_IBM_PBLOCK;
+		pb->curVals[0] = NULL;
+		pb->numParams = 1;
+	}
+	return pb;
+#endif /* LDAP_SLAPI */
+	return NULL;
+}
+
+void 
+slapi_pblock_destroy( Slapi_PBlock* pb ) 
+{
+#if defined(LDAP_SLAPI)
+	char *str = NULL;
+
+	get( pb, SLAPI_CONN_DN,(void **)&str );
+	if ( str != NULL ) {
+		ch_free( str );
+		str = NULL;
+	}
+
+	get( pb, SLAPI_CONN_AUTHTYPE, (void **)&str );
+	if ( str != NULL ) {
+		ch_free( str );
+		str = NULL;
+	}
+
+	get( pb, SLAPI_IBM_CONN_DN_ALT, (void **)&str );
+	if ( str != NULL ) {
+		ch_free( str );
+		str = NULL;
+	}
+
+	get( pb, SLAPI_IBM_CONN_DN_ORIG, (void **)&str );
+	if ( str != NULL ) {
+		ch_free( str );
+	}
+
+	ldap_pvt_thread_mutex_destroy( &pb->pblockMutex );
+
+	ch_free( pb ); 
+#endif /* LDAP_SLAPI */
+}
+
+int 
+slapi_pblock_get( Slapi_PBlock *pb, int arg, void *value ) 
+{
+#if defined(LDAP_SLAPI)
+	return get( pb, arg, (void **)value );
+#endif /* LDAP_SLAPI */
+	return PBLOCK_ERROR;
+}
+
+int 
+slapi_pblock_set( Slapi_PBlock *pb, int arg, void *value ) 
+{
+#if defined(LDAP_SLAPI)
+	void *pTmp = NULL;
+
+	switch ( arg ) {
+        case SLAPI_CONN_DN:
+        case SLAPI_CONN_AUTHTYPE:
+        case SLAPI_IBM_CONN_DN_ALT:
+        case SLAPI_IBM_CONN_DN_ORIG:
+		if ( value != NULL ) {
+			pTmp = (void *)slapi_ch_strdup((char *)value);
+			if ( pTmp == NULL ) {
+				return LDAP_NO_MEMORY;
+			}
+		}
+		break;
+	default:
+		pTmp = value;
+		break;
+	}
+	return set( pb, arg, pTmp );
+#endif /* LDAP_SLAPI */
+	return LDAP_NO_MEMORY;
+}
+
+void
+slapi_pblock_clear( Slapi_PBlock *pb ) 
+{
+#if defined(LDAP_SLAPI)
+   clearPB( pb );
+#endif /* LDAP_SLAPI */
+}
+
+int 
+slapi_pblock_delete_param( Slapi_PBlock *p, int param ) 
+{
+#if defined(LDAP_SLAPI)
+	return deleteParam( p, param );
+#endif /* LDAP_SLAPI */
+	return PBLOCK_ERROR;
+}
+
+void
+slapi_pblock_check_params( Slapi_PBlock *pb, int flag ) 
+{
+#if defined(LDAP_SLAPI)
+	checkParams( pb, flag );
+#endif /* LDAP_SLAPI */
+}
+
diff --git a/servers/slapd/slapi/slapi_pblock.h b/servers/slapd/slapi/slapi_pblock.h
new file mode 100644
index 0000000000..d5087a8d6c
--- /dev/null
+++ b/servers/slapd/slapi/slapi_pblock.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ * (C) Copyright IBM Corp. 1997,2002
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is 
+ * given to IBM Corporation. This software is provided ``as is'' 
+ * without express or implied warranty.
+ */
+
+#ifndef SLAPI_PBLOCK_H
+#define SLAPI_PBLOCK_H
+
+#define CMP_EQUAL 0
+#define CMP_GREATER 1
+#define CMP_LOWER (-1)
+#define PBLOCK_ERROR (-1)
+#define INVALID_PARAM PBLOCK_ERROR
+#define MAX_PARAMS 100
+
+struct slapi_pblock {
+	ldap_pvt_thread_mutex_t	pblockMutex;
+	int			ckParams;
+	int			numParams;
+	int			curParams[MAX_PARAMS];
+	void			*curVals[MAX_PARAMS];
+};
+
+Slapi_PBlock *slapi_pblock_new();
+void slapi_pblock_destroy( Slapi_PBlock* );
+int slapi_pblock_get( Slapi_PBlock *pb, int arg, void *value );
+int slapi_pblock_set( Slapi_PBlock *pb, int arg, void *value );
+void slapi_pblock_check_params(Slapi_PBlock *pb, int flag);
+int slapi_pblock_delete_param(Slapi_PBlock *p, int param);
+void slapi_pblock_clear(Slapi_PBlock *pb); 
+
+#endif /* SLAPI_PBLOCK_H */
+
diff --git a/servers/slapd/slapi/slapi_utils.c b/servers/slapd/slapi/slapi_utils.c
new file mode 100644
index 0000000000..2c90e82b99
--- /dev/null
+++ b/servers/slapd/slapi/slapi_utils.c
@@ -0,0 +1,1132 @@
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ * (C) Copyright IBM Corp. 1997,2002
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is 
+ * given to IBM Corporation. This software is provided ``as is'' 
+ * without express or implied warranty.
+ */
+
+#include "portable.h"
+#include "slapi_common.h"
+
+#include <slap.h>
+#include <slapi.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <slap.h>
+#include <unistd.h>
+#include <ldap_pvt.h>
+
+struct berval *ns_get_supported_extop( int );
+
+#ifdef _SPARC  
+#include <sys/systeminfo.h>
+#endif
+
+#include <netdb.h>
+
+/*
+ * server start time (should we use a struct timeval also in slapd?
+ */
+static struct			timeval base_time;
+ldap_pvt_thread_mutex_t		slapi_hn_mutex;
+ldap_pvt_thread_mutex_t		slapi_time_mutex;
+
+/*
+ * This function converts an array of pointers to berval objects to
+ * an array of berval objects.
+ */
+
+int
+bvptr2obj(
+	struct berval	**bvptr, 
+	BerVarray	*bvobj )
+{
+	int		rc = LDAP_SUCCESS;
+	int		i;
+	BerVarray	tmpberval;
+
+	if ( bvptr == NULL || *bvptr == NULL ) {
+		return LDAP_OTHER;
+	}
+
+	for ( i = 0; bvptr != NULL && bvptr[i] != NULL; i++ ) {
+		; /* EMPTY */
+	}
+
+	tmpberval = (BerVarray)slapi_ch_malloc( (i + 1)*sizeof(struct berval));
+	if ( tmpberval == NULL ) {
+		return LDAP_NO_MEMORY;
+	} 
+
+	for ( i = 0; bvptr[i] != NULL; i++ ) {
+		tmpberval[i].bv_val = bvptr[i]->bv_val;
+		tmpberval[i].bv_len = bvptr[i]->bv_len;
+	}
+
+	if ( rc == LDAP_SUCCESS ) {
+		*bvobj = tmpberval;
+	}
+
+	return rc;
+}
+
+Slapi_Entry *
+slapi_str2entry(
+	char		*s, 
+	int		check_dup )
+{
+#if defined(LDAP_SLAPI)
+	Slapi_Entry	*e = NULL;
+	char		*pTmpS;
+
+	pTmpS = slapi_ch_strdup( s );
+	if ( pTmpS != NULL ) {
+		e = str2entry( pTmpS ); 
+		slapi_ch_free( pTmpS );
+	}
+
+	return e;
+#else /* !defined(LDAP_SLAPI) */
+	return NULL;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+char *
+slapi_entry2str(
+	Slapi_Entry	*e, 
+	int		*len ) 
+{
+#if defined(LDAP_SLAPI)
+	char		*ret;
+
+	ldap_pvt_thread_mutex_lock( &entry2str_mutex );
+	ret = entry2str( e, len );
+	ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
+
+	return ret;
+#else /* !defined(LDAP_SLAPI) */
+	return NULL;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+char *
+slapi_entry_get_dn( Slapi_Entry *e ) 
+{
+#if defined(LDAP_SLAPI)
+	return e->e_name.bv_val;
+#else /* !defined(LDAP_SLAPI) */
+	return NULL;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+void 
+slapi_entry_set_dn(
+	Slapi_Entry	*e, 
+	char		*ldn )
+{
+#if defined(LDAP_SLAPI)
+	struct berval	dn = { 0, NULL };
+
+	dn.bv_val = ldn;
+	dn.bv_len = strlen( ldn );
+
+	dnPrettyNormal( NULL, &dn, &e->e_name, &e->e_nname );
+#endif /* defined(LDAP_SLAPI) */
+}
+
+Slapi_Entry *
+slapi_entry_dup( Slapi_Entry *e ) 
+{
+#if defined(LDAP_SLAPI)
+	char		*tmp = NULL;
+	Slapi_Entry	*tmpEnt;
+	int		len = 0;
+	
+	tmp = slapi_entry2str( e, &len );
+	if ( tmp == NULL ) {
+		return (Slapi_Entry *)NULL;
+	}
+
+	tmpEnt = (Slapi_Entry *)str2entry( tmp );
+	if ( tmpEnt == NULL ) { 
+		slapi_ch_free( tmp );
+		return (Slapi_Entry *)NULL;
+	}
+	
+	if (tmp != NULL) {
+		slapi_ch_free( tmp );
+	}
+
+	return tmpEnt;
+#else /* !defined(LDAP_SLAPI) */
+	return NULL;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+int 
+slapi_entry_attr_delete(
+	Slapi_Entry	*e, 		
+	char		*type ) 
+{
+#if defined(LDAP_SLAPI)
+	AttributeDescription	*ad;
+	const char		*text;
+
+	if ( slap_str2ad( type, &ad, &text ) != LDAP_SUCCESS ) {
+		return 1;	/* LDAP_NO_SUCH_ATTRIBUTE */
+	}
+
+	if ( attr_delete( &e->e_attrs, ad ) == LDAP_SUCCESS ) {
+		return 0;	/* attribute is deleted */
+	} else {
+		return -1;	/* something went wrong */
+	}
+#else /* !defined(LDAP_SLAPI) */
+	return -1;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+Slapi_Entry *
+slapi_entry_alloc( void ) 
+{
+#if defined(LDAP_SLAPI)
+	return (Slapi_Entry *)slapi_ch_calloc( 1, sizeof(Slapi_Entry) );
+#else /* !defined(LDAP_SLAPI) */
+	return NULL;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+void 
+slapi_entry_free( Slapi_Entry *e ) 
+{
+#if defined(LDAP_SLAPI)
+	entry_free( e );
+#endif /* defined(LDAP_SLAPI) */
+}
+
+int 
+slapi_entry_attr_merge(
+	Slapi_Entry	*e, 
+	char		*type, 
+	struct berval	**vals ) 
+{
+#if defined(LDAP_SLAPI)
+	AttributeDescription	*ad;
+	const char		*text;
+	BerVarray		bv;
+	int			rc;
+
+	rc = bvptr2obj( vals, &bv );
+	if ( rc != LDAP_SUCCESS ) {
+		return -1;
+	}
+	
+	rc = slap_str2ad( type, &ad, &text );
+	if ( rc != LDAP_SUCCESS ) {
+		return -1;
+	}
+	
+	rc = attr_merge( e, ad, bv );
+	ch_free( bv );
+
+	return rc;
+#else /* !defined(LDAP_SLAPI) */
+	return -1;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+int
+slapi_entry_attr_find(
+	Slapi_Entry	*e, 
+	char		*type, 
+	Slapi_Attr	**attr ) 
+{
+#if defined(LDAP_SLAPI)
+	AttributeDescription	*ad;
+	const char		*text;
+	int			rc;
+
+	rc = slap_str2ad( type, &ad, &text );
+	if ( rc != LDAP_SUCCESS ) {
+		return -1;
+	}
+
+	*attr = attr_find( e->e_attrs, ad );
+	if ( *attr == NULL ) {
+		return -1;
+	}
+
+	return 0;
+#else /* !defined(LDAP_SLAPI) */
+	return -1;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+/* 
+ * FIXME -- The caller must free the allocated memory. 
+ * In Netscape they do not have to.
+ */
+int 
+slapi_attr_get_values(
+	Slapi_Attr	*attr, 
+	struct berval	***vals ) 
+{
+#if defined(LDAP_SLAPI)
+	int		i, j;
+	struct berval	**bv;
+
+	if ( attr == NULL ) {
+		return 1;
+	}
+
+	for ( i = 0; attr->a_vals[i].bv_val != NULL; i++ ) {
+		; /* EMPTY */
+	}
+
+	bv = (struct berval **)ch_malloc( (i + 1) * sizeof(struct berval *) );
+	for ( j = 0; j < i; j++ ) {
+		bv[j] = (struct berval *)ch_malloc( sizeof(struct berval) );
+		bv[j]->bv_val = ch_strdup( attr->a_vals[j].bv_val );
+		bv[j]->bv_len = attr->a_vals[j].bv_len;
+	}
+	bv[j] = NULL;
+	
+	*vals = (struct berval **)bv;
+
+	return 0;
+#else /* !defined(LDAP_SLAPI) */
+	return -1;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+char *
+slapi_dn_normalize( char *dn ) 
+{
+#if defined(LDAP_SLAPI)
+	struct berval	bdn;
+	struct berval	ndn;
+
+	assert( dn != NULL );
+	
+	bdn.bv_val = dn;
+	bdn.bv_len = strlen( dn );
+
+	dnNormalize2( NULL, &bdn, &ndn );
+
+	/*
+	 * FIXME: ain't it safe to set dn = ndn.bv_val ?
+	 */
+	dn = ch_strdup( ndn.bv_val );
+	ch_free( ndn.bv_val );
+	
+	return dn;
+#else /* !defined(LDAP_SLAPI) */
+	return NULL;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+/*
+ * FIXME: this function is dangerous and should be deprecated;
+ * DN normalization is a lot more than lower-casing, and BTW
+ * OpenLDAP's DN normalization for case insensitive attributes
+ * is already lower case
+ */
+char *
+slapi_dn_normalize_case( char *dn ) 
+{
+#if defined(LDAP_SLAPI)
+	slapi_dn_normalize( dn );
+	ldap_pvt_str2lower( dn );
+
+	return dn;
+#else /* defined(LDAP_SLAPI) */
+	return NULL;
+#endif /* defined(LDAP_SLAPI) */
+}
+
+int 
+slapi_dn_issuffix(
+	char		*dn, 
+	char		*suffix )
+{
+#if defined(LDAP_SLAPI)
+	struct berval	bdn, ndn;
+	struct berval	bsuffix, nsuffix;
+
+	assert( dn != NULL );
+	assert( suffix != NULL );
+
+	bdn.bv_val = dn;
+	bdn.bv_len = strlen( dn );
+
+	bsuffix.bv_val = suffix;
+	bsuffix.bv_len = strlen( suffix );
+
+	dnNormalize2( NULL, &bdn, &ndn );
+	dnNormalize2( NULL, &bsuffix, &nsuffix );
+
+	return dnIsSuffix( &ndn, &nsuffix );
+#else /* !defined(LDAP_SLAPI) */
+	return 0;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+char *
+slapi_dn_ignore_case( char *dn )
+{       
+#if defined(LDAP_SLAPI)
+	return slapi_dn_normalize_case( dn );
+#else /* !defined(LDAP_SLAPI) */
+	return NULL;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+char *
+slapi_ch_malloc( unsigned long size ) 
+{
+#if defined(LDAP_SLAPI)
+	return ch_malloc( size );	
+#else /* !defined(LDAP_SLAPI) */
+	return NULL;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+void 
+slapi_ch_free( void *ptr ) 
+{
+#if defined(LDAP_SLAPI)
+#if 0
+	if ( ptr != NULL )	/* not required ... */
+#endif /* 0 */
+		ch_free( ptr );
+#endif /* defined(LDAP_SLAPI) */
+}
+
+char *
+slapi_ch_calloc(
+	unsigned long nelem, 
+	unsigned long size ) 
+{
+#if defined(LDAP_SLAPI)
+	return ch_calloc( nelem, size );
+#else /* !defined(LDAP_SLAPI) */
+	return NULL;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+char *
+slapi_ch_realloc(
+	char *block, 
+	unsigned long size ) 
+{
+#if defined(LDAP_SLAPI)
+	return ch_realloc( block, size );
+#else /* !defined(LDAP_SLAPI) */
+	return NULL;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+char *
+slapi_ch_strdup( char *s ) 
+{
+#if defined(LDAP_SLAPI)
+	return ch_strdup( (const char *)s );
+#else /* !defined(LDAP_SLAPI) */
+	return NULL;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+size_t
+slapi_ch_stlen( char *s ) 
+{
+#if defined(LDAP_SLAPI)
+	return strlen( (const char *)s );
+#else /* !defined(LDAP_SLAPI) */
+	return 0;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+int 
+slapi_control_present(
+	LDAPControl	**controls, 
+	char		*oid, 
+	struct berval	**val, 
+	int		*iscritical ) 
+{
+#if defined(LDAP_SLAPI)
+	int		i;
+	int		rc = 0;
+
+	if ( val ) {
+		*val = NULL;
+	}
+	
+	if ( iscritical ) {
+		*iscritical = 0;
+	}
+	
+	for ( i = 0; controls != NULL && controls[i] != NULL; i++ ) {
+		if ( strcmp( controls[i]->ldctl_oid, oid ) != 0 ) {
+			continue;
+		}
+
+		rc = 1;
+		if ( controls[i]->ldctl_value.bv_len != 0 ) {
+			/*
+			 * FIXME: according to 6.1 specification,
+			 *    "The val output parameter is set
+			 *    to point into the controls array.
+			 *    A copy of the control value is
+			 *    not made."
+			 */
+#if 0
+			struct berval	*pTmpBval;
+
+			pTmpBval = (struct berval *)slapi_ch_malloc( sizeof(struct berval));
+			if ( pTmpBval == NULL ) {
+				rc = 0;
+			} else {
+				pTmpBval->bv_len = controls[i]->ldctl_value.bv_len;
+				pTmpBval->bv_val = controls[i]->ldctl_value.bv_val;
+				if ( val ) {
+					*val = pTmpBval;
+				} else {
+					slapi_ch_free( pTmpBval );
+					rc = 0;
+				}
+			}
+#endif /* 0 */
+			if ( val ) {
+				*val = &controls[i]->ldctl_value;
+			}
+		}
+
+		if ( iscritical ) {
+			*iscritical = controls[i]->ldctl_iscritical;
+		}
+
+		break;
+	}
+
+	return rc;
+#else /* !defined(LDAP_SLAPI) */
+	return 0;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+void 
+slapi_register_supported_control(
+	char		*controloid, 
+	unsigned long	controlops )
+{
+#if defined(LDAP_SLAPI)
+	/* FIXME -- can not add controls to openLDAP dynamically */
+	slapi_log_error( SLAPI_LOG_FATAL, "SLAPI_CONTROLS",
+			"can not add controls to openLDAP dynamically\n" );
+#endif /* defined(LDAP_SLAPI) */
+}
+
+int 
+slapi_get_supported_controls(
+	char		***ctrloidsp, 
+	unsigned long	**ctrlopsp ) 
+{
+#if defined(LDAP_SLAPI)
+	int		i, n;
+	int		rc = 1;
+	char		**oids = NULL;
+	unsigned long	*masks = NULL;
+
+	for (n = 0; get_supported_ctrl( n ) != NULL; n++) {
+		; /* count them */
+	}
+	
+	if ( n == 0 ) {
+		/* no controls */
+		*ctrloidsp = NULL;
+		*ctrlopsp = NULL;
+		return LDAP_SUCCESS;
+	}
+
+
+	oids = (char **)slapi_ch_malloc( (n + 1) * sizeof(char *) );
+	if ( oids == NULL ) {
+		rc = LDAP_NO_MEMORY;
+		goto error_return;
+	}
+
+	masks = (unsigned long *)slapi_ch_malloc( n * sizeof(int) );
+	if ( masks == NULL ) {
+		rc = LDAP_NO_MEMORY;
+		goto error_return;
+	}
+
+	for ( i = 0; i < n; i++ ) {
+		/*
+		 * FIXME: Netscape's specification says nothing about
+		 * memory; should we copy the OIDs or return pointers
+		 * to internal values? In OpenLDAP the latter is safe
+		 * since we do not allow to register coltrols runtime
+		 */
+		oids[ i ] = ch_strdup( get_supported_ctrl( i ) );
+		if ( oids[ i ] == NULL ) {
+			rc = LDAP_NO_MEMORY;
+			goto error_return;
+		}
+		masks[ i ] = (unsigned long)get_supported_ctrl_mask( i );
+	}
+
+	*ctrloidsp = oids;
+	*ctrlopsp = masks;
+	return LDAP_SUCCESS;
+
+error_return:
+	if ( rc != LDAP_SUCCESS ) {
+		for ( i = 0; oids != NULL && oids[ i ] != NULL; i++ ) {
+			ch_free( oids[ i ] );
+		}
+		ch_free( oids );
+		ch_free( masks );
+	}
+
+	return rc;
+#else /* !defined(LDAP_SLAPI) */
+	return 1;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+void 
+slapi_register_supported_saslmechanism( char *mechanism )
+{
+#if defined(LDAP_SLAPI)
+	/* FIXME -- can not add saslmechanism to openLDAP dynamically */
+	slapi_log_error( SLAPI_LOG_FATAL, "SLAPI_SASL",
+			"can not add saslmechanism to openLDAP dynamically\n" );
+#endif /* defined(LDAP_SLAPI) */
+}
+
+char **
+slapi_get_supported_saslmechanisms( void )
+{
+#if defined(LDAP_SLAPI)
+	/* FIXME -- can not get the saslmechanism wihtout a connection. */
+	slapi_log_error( SLAPI_LOG_FATAL, "SLAPI_SASL",
+			"can not get the saslmechanism "
+			"wihtout a connection\n" );
+	return NULL;
+#else /* defined(LDAP_SLAPI) */
+	return NULL;
+#endif /* defined(LDAP_SLAPI) */
+}
+
+char **
+slapi_get_supported_extended_ops( void )
+{
+#if defined(LDAP_SLAPI)
+	int		i, j, k;
+	char		**ppExtOpOID = NULL;
+	int		numExtOps = 0;
+
+	for ( i = 0; get_supported_extop( i ) != NULL; i++ ) {
+		;
+	}
+	
+	for ( j = 0; ns_get_supported_extop( j ) != NULL; j++ ) {
+		;
+	}
+
+	numExtOps = i + j;
+	if ( numExtOps == 0 ) {
+		return NULL;
+	}
+
+	ppExtOpOID = (char **)slapi_ch_malloc( (numExtOps + 1) * sizeof(char *) );
+	for ( k = 0; k < i; k++ ) {
+		struct berval	*bv;
+
+		bv = get_supported_extop( k );
+		assert( bv != NULL );
+
+		ppExtOpOID[ k ] = bv->bv_val;
+	}
+	
+	for ( ; k < j; k++ ) {
+		struct berval	*bv;
+
+		bv = ns_get_supported_extop( k );
+		assert( bv != NULL );
+
+		ppExtOpOID[ i + k ] = bv->bv_val;
+	}
+	ppExtOpOID[ i + k ] = NULL;
+
+	return ppExtOpOID;
+#else /* !defined(LDAP_SLAPI) */
+	return NULL;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+void 
+slapi_send_ldap_result(
+	Slapi_PBlock	*pb, 
+	int		err, 
+	char		*matched, 
+	char		*text, 
+	int		nentries, 
+	struct berval	**urls ) 
+{
+#if defined(LDAP_SLAPI)
+	Connection	*conn;
+	Operation	*op;
+	struct berval	*s;
+	char		*extOID = NULL;
+	struct berval	*extValue = NULL;
+	int		rc;
+
+	slapi_pblock_get( pb, SLAPI_CONNECTION, &conn );
+	slapi_pblock_get( pb, SLAPI_OPERATION, &op );
+	if ( err == LDAP_SASL_BIND_IN_PROGRESS ) {
+		slapi_pblock_get( pb, SLAPI_BIND_RET_SASLCREDS, &s );
+		rc = LDAP_SASL_BIND_IN_PROGRESS;
+		send_ldap_sasl( conn, op, rc, NULL, NULL, NULL, NULL, s );
+		return;
+	}
+
+	slapi_pblock_get( pb, SLAPI_EXT_OP_RET_OID, &extOID );
+	if ( extOID != NULL ) {
+		slapi_pblock_get( pb, SLAPI_EXT_OP_RET_VALUE, &extValue );
+		slapi_send_ldap_extended_response( conn, op, err, extOID,
+				extValue );
+		return;
+	}
+
+	send_ldap_result( conn, op, err, matched, text, NULL, NULL );
+#endif /* defined(LDAP_SLAPI) */
+}
+
+int 
+slapi_send_ldap_search_entry(
+	Slapi_PBlock	*pb, 
+	Slapi_Entry	*e, 
+	LDAPControl	**ectrls, 
+	char		**attrs, 
+	int		attrsonly )
+{
+#if defined(LDAP_SLAPI)
+	Backend		*be;
+	Connection	*pConn;
+	Operation	*pOp;
+	int		rc;
+
+	int		i;
+	AttributeName	*an = NULL;
+	const char	*text;
+
+	for ( i = 0; attrs[ i ] != NULL; i++ ) {
+		; /* empty */
+	}
+
+	if ( i > 0 ) {
+		an = (AttributeName *) ch_malloc( i * sizeof(AttributeName) );
+		for ( i = 0; attrs[i] != NULL; i++ ) {
+			an[i].an_name.bv_val = ch_strdup( attrs[i] );
+			an[i].an_name.bv_len = strlen( attrs[i] );
+			an[i].an_desc = NULL;
+			if( slap_bv2ad( &an[i].an_name, &an[i].an_desc, &text ) != LDAP_SUCCESS)
+				return -1;
+		}
+	}
+
+	if ( ( rc = slapi_pblock_get( pb, SLAPI_BACKEND, (void *)&be ) != 0 ) ||
+			( rc = slapi_pblock_get( pb, SLAPI_CONNECTION, (void *)&pConn) != 0 ) ||
+			( rc = slapi_pblock_get( pb, SLAPI_OPERATION, (void *)&pOp) != 0 ) ) {
+		rc = LDAP_OTHER;
+	} else {
+		rc = send_search_entry( be, pConn, pOp, e, an, attrsonly, NULL );
+	}
+
+	return rc;
+
+#else /* !defined(LDAP_SLAPI) */
+	return -1;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+
+Slapi_Filter *
+slapi_str2filter( char *str ) 
+{
+#if defined(LDAP_SLAPI)
+	return str2filter( str );
+#else /* !defined(LDAP_SLAPI) */
+	return NULL;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+void 
+slapi_filter_free(
+	Slapi_Filter	*f, 
+	int		recurse ) 
+{
+#if defined(LDAP_SLAPI)
+	filter_free( f );
+#endif /* defined(LDAP_SLAPI) */
+}
+
+int 
+slapi_filter_get_choice( Slapi_Filter *f )
+{
+#if defined(LDAP_SLAPI)
+	int		rc;
+
+	if ( f != NULL ) {
+		rc = f->f_choice;
+	} else {
+		rc = 0;
+	}
+
+	return rc;
+#else /* !defined(LDAP_SLAPI) */
+	return -1;		/* invalid filter type */
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+int 
+slapi_filter_get_ava(
+	Slapi_Filter	*f, 
+	char		**type, 
+	struct berval	**bval )
+{
+#if defined(LDAP_SLAPI)
+	int		ftype;
+	int		rc = LDAP_SUCCESS;
+
+	assert( type != NULL );
+	assert( bval != NULL );
+
+	*type = NULL;
+	*bval = NULL;
+
+	ftype = f->f_choice;
+	if ( ftype == LDAP_FILTER_EQUALITY 
+			|| ftype ==  LDAP_FILTER_GE 
+			|| ftype == LDAP_FILTER_LE 
+			|| ftype == LDAP_FILTER_APPROX ) {
+		*type = slapi_ch_strdup( f->f_un.f_un_ava->aa_desc->ad_cname.bv_val );
+		if ( *type == NULL ) {
+			rc = LDAP_NO_MEMORY;
+			goto done;
+		}
+
+		*bval = (struct berval *)slapi_ch_malloc( sizeof(struct berval) );
+		if ( *bval == NULL ) {
+			rc = LDAP_NO_MEMORY;
+			goto done;
+		}
+
+		(*bval)->bv_len = f->f_un.f_un_ava->aa_value.bv_len;
+		(*bval)->bv_val = slapi_ch_strdup( f->f_un.f_un_ava->aa_value.bv_val );
+		if ( (*bval)->bv_val == NULL ) {
+			rc = LDAP_NO_MEMORY;
+			goto done;
+		}
+	} else { /* filter type not supported */
+		rc = -1;
+	}
+
+done:
+	if ( rc != LDAP_SUCCESS ) {
+		if ( *bval ) {
+			ch_free( *bval );
+			*bval = NULL;
+		}
+
+		if ( *type ) {
+			ch_free( *type );
+			*type = NULL;
+		}
+	}
+
+	return rc;
+#else /* !defined(LDAP_SLAPI) */
+	return -1;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+Slapi_Filter *
+slapi_filter_list_first( Slapi_Filter *f )
+{
+#if defined(LDAP_SLAPI)
+	int		ftype;
+
+	if ( f == NULL ) {
+		return NULL;
+	}
+
+	ftype = f->f_choice;
+	if ( ftype == LDAP_FILTER_AND
+			|| ftype == LDAP_FILTER_OR
+			|| ftype == LDAP_FILTER_NOT ) {
+		return (Slapi_Filter *)f->f_and;
+	} else {
+		return NULL;
+	}
+#else /* !defined(LDAP_SLAPI) */
+	return NULL;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+Slapi_Filter *
+slapi_filter_list_next(
+	Slapi_Filter	*f, 
+	Slapi_Filter	*fprev )
+{
+#if defined(LDAP_SLAPI)
+	int		ftype;
+
+	if ( f == NULL ) {
+		return NULL;
+	}
+
+	ftype = f->f_choice;
+	if ( ftype == LDAP_FILTER_AND
+			|| ftype == LDAP_FILTER_OR
+			|| ftype == LDAP_FILTER_NOT ) {
+		if ( f->f_and == fprev ) {
+			return f->f_and->f_next;
+		}
+	}
+
+	return NULL;
+#else /* !defined(LDAP_SLAPI) */
+	return NULL;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+int 
+slapi_send_ldap_extended_response(
+	Connection	*conn, 
+	Operation	*op,
+	int		errornum, 
+	char		*respName,
+	struct berval	*response )
+{
+#if defined(LDAP_SLAPI)
+	send_ldap_extended( conn,op, errornum, NULL, NULL, NULL,
+			respName,response, NULL );
+	return LDAP_SUCCESS;
+#else /* !defined(LDAP_SLAPI) */
+	return -1;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+int 
+slapi_pw_find(
+	struct berval	**vals, 
+	struct berval	*v ) 
+{
+#if defined(LDAP_SLAPI)
+	/*
+	 * FIXME: what's the point?
+	 */
+	return 1;
+#else /* !defined(LDAP_SLAPI) */
+	return 1;
+#endif /* !defined(LDAP_SLAPI) */
+}
+             
+char *
+slapi_get_hostname( void ) 
+{
+#if defined(LDAP_SLAPI)
+	char		*hn = NULL;
+
+	/*
+	 * FIXME: I'd prefer a different check ...
+	 */
+#if defined _SPARC 
+	hn = (char *)slapi_ch_malloc( MAX_HOSTNAME );
+	if ( hn == NULL) {
+		slapi_log_error( SLAPI_LOG_FATAL, "SLAPI_SYSINFO",
+				"can't malloc memory for hostname\n" );
+		hn = NULL;
+		
+	} else if ( sysinfo( SI_HOSTNAME, hn, MAX_HOSTNAME ) < 0 ) {
+		slapi_log_error( SLAPI_LOG_FATAL, "SLAPI_SYSINFO",
+				"can't get hostname\n" );
+		slapi_ch_free( hn );
+		hn = NULL;
+	}
+#else /* !_SPARC */
+	static int	been_here = 0;   
+	static char	*static_hn = NULL;
+
+	ldap_pvt_thread_mutex_lock( &slapi_hn_mutex );
+	if ( !been_here ) {
+		static_hn = (char *)slapi_ch_malloc( MAX_HOSTNAME );
+		if ( static_hn == NULL) {
+			slapi_log_error( SLAPI_LOG_FATAL, "SLAPI_SYSINFO",
+					"can't malloc memory for hostname\n" );
+			static_hn = NULL;
+			ldap_pvt_thread_mutex_unlock( &slapi_hn_mutex );
+
+			return hn;
+			
+		} else { 
+			if ( gethostname( static_hn, MAX_HOSTNAME ) != 0 ) {
+				slapi_log_error( SLAPI_LOG_FATAL,
+						"SLAPI_SYSINFO",
+						"can't get hostname\n" );
+				slapi_ch_free( static_hn );
+				static_hn = NULL;
+				ldap_pvt_thread_mutex_unlock( &slapi_hn_mutex );
+
+				return hn;
+
+			} else {
+				been_here = 1;
+			}
+		}
+	}
+	ldap_pvt_thread_mutex_unlock( &slapi_hn_mutex );
+	
+	hn = ch_strdup( static_hn );
+#endif /* !_SPARC */
+
+	return hn;
+#else /* !defined(LDAP_SLAPI) */
+	return NULL;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+/*
+ * FIXME: this should go in an appropriate header ...
+ */
+extern int vLogError( int level, char *subsystem, char *fmt, va_list arglist );
+
+int 
+slapi_log_error(
+	int		severity, 
+	char		*subsystem, 
+	char		*fmt, 
+	... ) 
+{
+#if defined(LDAP_SLAPI)
+	int		rc = LDAP_SUCCESS;
+	va_list		arglist;
+
+	va_start( arglist, fmt );
+	rc = vLogError( severity, subsystem, fmt, arglist );
+	va_end( arglist );
+
+	return rc;
+#else /* !defined(LDAP_SLAPI) */
+	return -1;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+
+unsigned long
+slapi_timer_current_time( void ) 
+{
+#if defined(LDAP_SLAPI)
+	static int	first_time = 1;
+#if !defined (_WIN32)
+	struct timeval	now;
+	unsigned long	ret;
+
+	ldap_pvt_thread_mutex_lock( &slapi_time_mutex );
+	if (first_time) {
+		first_time = 0;
+		gettimeofday( &base_time, NULL );
+	}
+	gettimeofday( &now, NULL );
+	ret = ( now.tv_sec  - base_time.tv_sec ) * 1000000 + 
+			(now.tv_usec - base_time.tv_usec);
+	ldap_pvt_thread_mutex_unlock( &slapi_time_mutex );
+
+	return ret;
+
+	/*
+	 * Ain't it better?
+	return (slap_get_time() - starttime) * 1000000;
+	 */
+#else /* _WIN32 */
+	LARGE_INTEGER now;
+
+	if ( first_time ) {
+		first_time = 0;
+		performance_counter_present = QueryPerformanceCounter( &base_time );
+		QueryPerformanceFrequency( &performance_freq );
+	}
+
+	if ( !performance_counter_present )
+	     return 0;
+
+	QueryPerformanceCounter( &now );
+	return (1000000*(now.QuadPart-base_time.QuadPart))/performance_freq.QuadPart;
+#endif /* _WIN32 */
+#else /* !defined(LDAP_SLAPI) */
+	return 0;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+/*
+ * FIXME ?
+ */
+unsigned long
+slapi_timer_get_time( char *label ) 
+{
+#if defined(LDAP_SLAPI)
+	unsigned long start = slapi_timer_current_time();
+	printf("%10ld %10ld usec %s\n", start, 0, label);
+	return start;
+#else /* !defined(LDAP_SLAPI) */
+	return 0;
+#endif /* !defined(LDAP_SLAPI) */
+}
+
+/*
+ * FIXME ?
+ */
+void
+slapi_timer_elapsed_time(
+	char *label,
+	unsigned long start ) 
+{
+#if defined(LDAP_SLAPI)
+	unsigned long stop = slapi_timer_current_time();
+	printf ("%10ld %10ld usec %s\n", stop, stop - start, label);
+#endif /* defined(LDAP_SLAPI) */
+}
+
+void
+slapi_free_search_results_internal( Slapi_PBlock *pb ) 
+{
+#if defined(LDAP_SLAPI)
+	Slapi_Entry	**entries;
+	int		k = 0, nEnt = 0;
+
+	slapi_pblock_get( pb, SLAPI_NENTRIES, &nEnt );
+	slapi_pblock_get( pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries );
+	if ( nEnt == 0 ) {
+		return;
+	}
+	
+	if ( entries == NULL ) {
+		return;
+	}
+	
+	for ( k = 0; k < nEnt; k++ ) {
+		slapi_entry_free( entries[k] );
+	}
+	
+	slapi_ch_free( entries );
+#endif /* defined(LDAP_SLAPI) */
+}
+
diff --git a/servers/slapd/slapi/slapi_utils.h b/servers/slapd/slapi/slapi_utils.h
new file mode 100644
index 0000000000..9bdd05b4d3
--- /dev/null
+++ b/servers/slapd/slapi/slapi_utils.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ * (C) Copyright IBM Corp. 1997,2002
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is 
+ * given to IBM Corporation. This software is provided ``as is'' 
+ * without express or implied warranty.
+ */
+
+#ifndef _SLAPI_UTILS_H
+#define _SLAPI_UTILS_H
+
+struct _Audit_record;
+typedef struct _Audit_record Audit_record;
+
+#define SLAPI_CONTROL_MANAGEDSAIT_OID "2.16.840.1.113730.3.4.2"
+#define SLAPI_CONTROL_SORTEDSEARCH_OID "1.2.840.113556.1.4.473"
+#define SLAPI_CONTROL_PAGED_RESULTS_OID "1.2.840.113556.1.4.319"
+
+typedef int (*SLAPI_FUNC)(Slapi_PBlock *pb);
+
+#define MAX_HOSTNAME 512
+
+#define DOMAIN "Domain"
+#define TCPIPPATH "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"
+
+typedef struct _slapi_control {
+        int           s_ctrl_num;
+        char          **s_ctrl_oids;
+        unsigned long *s_ctrl_ops;
+} Slapi_Control;
+
+typedef struct _ExtendedOp {
+	struct berval ext_oid;
+        SLAPI_FUNC ext_func;
+        Backend    *ext_be;
+        struct _ExtendedOp *ext_next;
+} ExtendedOp;
+
+int slapi_log_error( int severity, char *subsystem, char *fmt, ... );
+Slapi_Entry *slapi_str2entry( char *s, int flags );
+char *slapi_entry2str( Slapi_Entry *e, int *len );
+int slapi_entry_attr_merge( Slapi_Entry *e, char *type, struct berval **vals );
+int slapi_entry_attr_find( Slapi_Entry *e, char *type, Slapi_Attr **attr );
+int slapi_entry_attr_delete( Slapi_Entry *e, char *type );
+char *slapi_entry_get_dn( Slapi_Entry *e );
+void slapi_entry_set_dn( Slapi_Entry *e, char *dn );
+Slapi_Entry *slapi_entry_dup( Slapi_Entry *e );
+Slapi_Entry *slapi_entry_alloc();
+void slapi_entry_free( Slapi_Entry *e );
+int slapi_attr_get_values( Slapi_Attr *attr, struct berval ***vals );
+char *slapi_ch_malloc( unsigned long size );
+void slapi_ch_free( void *ptr );
+char *slapi_ch_calloc( unsigned long nelem, unsigned long size );
+char *slapi_ch_realloc( char *block, unsigned long size );
+char *slapi_ch_strdup( char *s );
+/*
+ * FIXME: these two were missing, but widely used in a couple of .c files
+ */
+size_t slapi_strlen(char *s );
+#define slapi_ch_stlen(s)	slapi_strlen(s)
+/* end of FIXME */
+char *slapi_dn_normalize( char *dn );
+char *slapi_dn_normalize_case( char *dn );
+char * slapi_esc_dn_normalize( char *dn );
+char * slapi_esc_dn_normalize_case( char *dn );
+int slapi_dn_isroot( Slapi_PBlock *pb, char *dn );
+int slapi_dn_issuffix( char *dn, char *suffix );
+char *slapi_dn_ignore_case( char *dn );
+char *slapi_get_hostname();
+void slapi_register_supported_saslmechanism( char *mechanism );
+void slapi_send_ldap_result( Slapi_PBlock *pb, int err, 
+	char *matched, char *text, int nentries, struct berval **urls );
+int slapi_send_ldap_extended_response(Connection *conn, Operation *op, 
+			int errornum, char *respName, struct berval *response);
+int slapi_send_ldap_search_entry( Slapi_PBlock *pb, Slapi_Entry *e, 
+			LDAPControl **ectrls, char **attrs, int attrsonly ); 
+void slapi_register_supported_control(char *controloid, 
+					unsigned long controlops);
+int slapi_get_supported_controls(char ***ctrloidsp, unsigned long **ctrlopsp);
+int slapi_control_present( LDAPControl **controls, char *oid, 
+				struct berval **val, int *iscritical);
+void slapi_register_supported_saslmechanism(char *mechanism);
+char **slapi_get_supported_saslmechanisms();
+char **slapi_get_supported_extended_ops(void);
+int checkControlHonored(LDAPControl **controls, char *pControlOid, 
+				unsigned long operation, int *isHonored );
+void slapi_broadcast_be(int funcType, Slapi_PBlock *pPB);
+Slapi_Filter *slapi_str2filter( char *str );
+void slapi_filter_free( Slapi_Filter *f, int recurse );
+int slapi_filter_get_choice( Slapi_Filter *f);
+int slapi_filter_get_ava( Slapi_Filter *f, char **type, struct berval **bval );
+Slapi_Filter *slapi_filter_list_first( Slapi_Filter *f );
+Slapi_Filter *slapi_filter_list_next( Slapi_Filter *f, Slapi_Filter *fprev );
+void slapi_free_search_results_internal(Slapi_PBlock *pb);
+int slapi_is_connection_ssl(Slapi_PBlock *pPB, int *isSSL);
+int slapi_get_client_port(Slapi_PBlock *pPB, int *fromPort);
+int slapi_get_num_be(char *type);
+unsigned long slapi_timer_current_time();
+unsigned long slapi_timer_get_time(char *label);
+void slapi_timer_elapsed_time(char *label,unsigned long start);
+int slapi_audit_init_header( Connection *conn, Operation *op, 
+		Audit_record **arp, void **audit_op_str, 	
+		int audit_op, int audit_ext_op, int audit_op_str_len); 
+int slapi_audit_send_record( Slapi_PBlock *pb, Connection *conn, 
+						Operation *op, int rc);
+
+extern ldap_pvt_thread_mutex_t	slapi_hn_mutex;
+extern ldap_pvt_thread_mutex_t	slapi_time_mutex;
+
+#endif /* _SLAPI_UTILS_H */
+
diff --git a/servers/slapd/tools/Makefile.in b/servers/slapd/tools/Makefile.in
index bed694b502..c700c8816f 100644
--- a/servers/slapd/tools/Makefile.in
+++ b/servers/slapd/tools/Makefile.in
@@ -27,7 +27,8 @@ XLIBS = $(SLAPD_L) $(LDBM_LIBS)
 XXLIBS = $(SLAPD_LIBS) \
 	$(LDBM_LIBS) $(SECURITY_LIBS) \
 	$(LDIF_LIBS) $(LUTIL_LIBS)
-XXXLIBS = $(MODULES_LIBS) $(LTHREAD_LIBS)
+XXXLIBS = $(MODULES_LIBS) $(LTHREAD_LIBS) \
+	$(SLAPI_LIBS) ../libslapi.a
 
 STATIC_DEPENDS=@SLAPD_NO_STATIC@ ../libbackends.a
 
diff --git a/servers/slapd/tools/mimic.c b/servers/slapd/tools/mimic.c
index 70f87c3ddd..355752ac71 100644
--- a/servers/slapd/tools/mimic.c
+++ b/servers/slapd/tools/mimic.c
@@ -42,7 +42,7 @@ send_ldap_disconnect(
 }
 
 void
-send_ldap_extended(
+slap_send_ldap_extended(
     Connection	*conn,
     Operation	*op,
     ber_int_t	err,
@@ -73,7 +73,7 @@ send_ldap_sasl(
 }
 
 void
-send_ldap_result(
+slap_send_ldap_result(
 	Connection  *conn, 
 	Operation   *op,
 	ber_int_t     err,
@@ -87,7 +87,7 @@ send_ldap_result(
 }
 
 void
-send_search_result(
+slap_send_search_result(
 	Connection  *conn, 
 	Operation   *op,
 	ber_int_t     err,
@@ -102,7 +102,7 @@ send_search_result(
 }
 
 int
-send_search_entry(
+slap_send_search_entry(
 	Backend *be,
 	Connection  *conn, 
 	Operation   *op,
@@ -116,7 +116,8 @@ send_search_entry(
 	return -1;
 }
 
-int send_search_reference(
+int
+slap_send_search_reference(
 	Backend *be,
 	Connection  *conn, 
 	Operation   *op,
@@ -270,6 +271,17 @@ slap_modrdn2mods(
 	return 0;
 }
 
+int
+slap_mods2entry(
+	Modifications *mods,
+	Entry **e,
+	int repl_user,
+	const char **text,
+	char *textbuf, size_t textlen )
+{
+	return 0;
+}
+
 int slap_sasl_getdn( Connection *conn, char *id, int len,
 	char *user_realm, struct berval *dn, int flags )
 {
-- 
GitLab