>From dcb0aad394c6d61e1f52576055a99f6391ab7ebc Mon Sep 17 00:00:00 2001
From: Noriko Hosoi <nhosoi@redhat.com>
Date: Fri, 28 Aug 2009 18:59:41 -0700
Subject: [PATCH] Plugin Default Config Entry

Design doc:
http://directory.fedoraproject.org/wiki/Entry_USN#Plugin_Default_Config_Entr

New slapi APIs in libslapd:
  int slapi_set_plugin_default_config(const char *type, Slapi_Value *value);
  Description: Add given "type: value" to the plugin default config entry
               (cn=plugin default config,cn=config) unless the same "type:
               value" pair already exists in the entry.
  Parameters: type - Attribute type to add to the default config entry
              value - Attribute value to add to the default config entry
  Return Value: 0 if the operation was successful
                non-0 if the operation was not successful

  int slapi_get_plugin_default_config(char *type, Slapi_ValueSet **valueset);
  Description: Get attribute values of given type from the plugin default
               config entry (cn=plugin default config,cn=config).
  Parameters: type - Attribute type to get from the default config entry
              valueset Valueset holding the attribute values
  Return Value: 0 if the operation was successful
              non-0 if the operation was not successful
  warning: Caller is responsible to free attrs by slapi_ch_array_free

Changes in the Replication plugin:
1) Functions to set replicated attributes
       agmt_set_replicated_attributes_from_attr and
       agmt_set_replicated_attributes_from_entry
   call _agmt_set_default_fractional_attrs to sets the default excluded
   attribute list from the plugin default config entry before setting
   them from each replication agreement.
   To support it, agmt_parse_excluded_attrs_config_attr is changed to be
   re-entrant.
2) Fixed a minor memory leak in the fractional attributes (ra->frac_attrs).
3) Added a check for the duplicated fractional attributes.

Changes in the USN plugin:
1) usn_start calls slapi_set_plugin_default_config to add "entryusn" to
   the EXCLUDE list of the value of nsds5ReplicatedAttributeList in the
   plugin default config entry.
2) fix for the bug 518673 - entryusn: wrong lastusn value; When the entryusn
   is not assigned yet, the next value to be set is 0.  Lastusn is calculate
   as (the next entryusn - 1).  Although the entryusn is 64-bit unsigned
   long, it should be printed as a 64-bit signed integer for lastusn.

Other:
Fixed a compiler error in ldap/servers/slapd/dse.c.
---
 ldap/servers/plugins/replication/repl5_agmt.c |  136 +++++++++++++++++----
 ldap/servers/plugins/usn/usn.c                |   40 +++++-
 ldap/servers/plugins/usn/usn.h                |    2 +-
 ldap/servers/slapd/dse.c                      |    7 +-
 ldap/servers/slapd/plugin.c                   |  156 +++++++++++++++++++++++++
 ldap/servers/slapd/proto-slap.h               |    2 +-
 ldap/servers/slapd/slapi-plugin.h             |   23 ++++
 ldap/servers/slapd/slapi-private.h            |    2 +
 8 files changed, 329 insertions(+), 39 deletions(-)

diff --git a/ldap/servers/plugins/replication/repl5_agmt.c b/ldap/servers/plugins/replication/repl5_agmt.c
index 613c222..dc9b3be 100644
--- a/ldap/servers/plugins/replication/repl5_agmt.c
+++ b/ldap/servers/plugins/replication/repl5_agmt.c
@@ -231,6 +231,7 @@ agmt_new_from_entry(Slapi_Entry *e)
 	Repl_Agmt *ra;
 	char *tmpstr;
 	Slapi_Attr *sattr;
+	char **denied_attrs = NULL;
 
 	char *auto_initialize = NULL;
 	char *val_nsds5BeginReplicaRefresh = "start";
@@ -396,27 +397,29 @@ agmt_new_from_entry(Slapi_Entry *e)
 	ra->last_init_status[0] = '\0';
 	
 	/* Fractional attributes */
-	if (slapi_entry_attr_find(e, type_nsds5ReplicatedAttributeList, &sattr) == 0)	
-	{
-			char **denied_attrs = NULL;
-			/* New set of excluded attributes */
-			if (agmt_set_replicated_attributes_from_attr(ra, sattr) != 0)
-            {
-                slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_add_callback: " 
-                                "failed to parse replicated attributes for agreement %s\n",
-                                agmt_get_long_name(ra));	
-            }
-			/* Check that there are no verboten attributes in the exclude list */
-			denied_attrs = agmt_validate_replicated_attributes(ra);
-			if (denied_attrs)
-			{
-				/* Report the error to the client */
-				slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "WARNING: "
-						"Attempt to exclude illegal attributes from a fractional agreement\n");
-				/* Free the list */
-				slapi_ch_array_free(denied_attrs);	
-				goto loser;
-			}
+	slapi_entry_attr_find(e, type_nsds5ReplicatedAttributeList, &sattr);
+
+	/* New set of excluded attributes */
+	/* Note: even if sattrs is empty, we have to call this func since there 
+	 * could be a default excluded attr list in cn=plugin default config */
+	if (agmt_set_replicated_attributes_from_attr(ra, sattr) != 0)
+	{
+		slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
+						"agmtlist_add_callback: failed to parse "
+						"replicated attributes for agreement %s\n",
+						agmt_get_long_name(ra));
+	}
+	/* Check that there are no verboten attributes in the exclude list */
+	denied_attrs = agmt_validate_replicated_attributes(ra);
+	if (denied_attrs)
+	{
+		/* Report the error to the client */
+		slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, 
+						"WARNING: Attempt to exclude illegal attributes "
+						"from a fractional agreement\n");
+		/* Free the list */
+		slapi_ch_array_free(denied_attrs);
+		goto loser;
 	}
 
 	if (!agmt_is_valid(ra))
@@ -488,6 +491,8 @@ agmt_delete(void **rap)
 	slapi_ch_free((void **)&(ra->hostname));
 	slapi_ch_free((void **)&(ra->binddn));
 
+	slapi_ch_array_free(ra->frac_attrs);
+
 	if (NULL != ra->creds)
 	{
 		/* XXX free berval */
@@ -1060,7 +1065,14 @@ agmt_parse_excluded_attrs_next(const char *attr_string, size_t *offset, char***
 		tmpstr = slapi_ch_malloc(stringlen + 1);
 		strncpy(tmpstr,beginstr,stringlen);
 		tmpstr[stringlen] = '\0';
-		charray_add(attrs,tmpstr);
+		if (charray_inlist(*attrs, tmpstr)) /* tmpstr is already in attrs */
+		{
+			slapi_ch_free_string(&tmpstr);
+		}
+		else
+		{
+			charray_add(attrs,tmpstr);
+		}
 		(*offset) += stringlen;
 		/* Skip a delimiting space */
 		if (c == ' ')
@@ -1073,17 +1085,22 @@ agmt_parse_excluded_attrs_next(const char *attr_string, size_t *offset, char***
 	}
 	return retval;
 }
- /* It looks like this:
- nsDS5ReplicatedAttributeList: (objectclass=*) $ EXCLUDE jpegPhoto telephoneNumber
+
+/* It looks like this:
+ * nsDS5ReplicatedAttributeList: (objectclass=*) $ EXCLUDE jpegPhoto telephoneNumber
+ * This function could be called multiple times: to set excluded attrs in the
+ * plugin default config and to set the ones in the replica agreement. 
+ * The excluded attrs from replica agreement are added to the ones from 
+ * default config.  (Therefore, *attrs should not be initialized in this 
+ * function.)
  */
 static int 
-agmt_parse_excluded_attrs_config_attr(const char *attr_string, char*** attrs)
+agmt_parse_excluded_attrs_config_attr(const char *attr_string, char ***attrs)
 {
 	int retval = 0;
 	size_t offset = 0;
 	char **new_attrs = NULL;
 
-	*attrs = NULL;
 	/* First parse and skip the filter */
 	retval = agmt_parse_excluded_attrs_filter(attr_string, &offset);
 	if (retval) 
@@ -1105,13 +1122,78 @@ agmt_parse_excluded_attrs_config_attr(const char *attr_string, char*** attrs)
 	retval = 0;
 	if (new_attrs) 
 	{
-		*attrs = new_attrs;
+		charray_merge_nodup(attrs, new_attrs, 1);
+		slapi_ch_array_free(new_attrs);
 	}
 error:
 	return retval;
 }
 
 /*
+ * _agmt_set_default_fractional_attrs
+ *   helper function to set nsds5ReplicatedAttributeList value (from cn=plugin
+ *   default config,cn=config) to frac_attrs in Repl_Agmt.  
+ *   nsds5ReplicatedAttributeList set in each agreement is added to the
+ *   default list set in this function.
+ */
+static int
+_agmt_set_default_fractional_attrs(Repl_Agmt *ra)
+{
+	Slapi_PBlock *newpb = NULL;
+	Slapi_Entry **entries = NULL;
+	int rc = LDAP_SUCCESS;
+	char *attrs[2];
+
+	attrs[0] = (char *)type_nsds5ReplicatedAttributeList;
+	attrs[1] = NULL;
+
+	newpb = slapi_pblock_new();
+	slapi_search_internal_set_pb(newpb,
+					SLAPI_PLUGIN_DEFAULT_CONFIG, /* Base DN */
+					LDAP_SCOPE_BASE,
+					"(objectclass=*)",
+					attrs, /* Attrs */
+					0, /* AttrOnly */
+					NULL, /* Controls */
+					NULL, /* UniqueID */
+					repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION),
+					0);
+	slapi_search_internal_pb(newpb);
+	slapi_pblock_get(newpb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
+	slapi_pblock_get(newpb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
+	ra->frac_attrs = NULL;
+	if (LDAP_SUCCESS == rc && entries && *entries) /* default config entry exists */
+	{
+		Slapi_Attr *attr;
+		Slapi_Value *sval = NULL;
+		if (0 == slapi_entry_attr_find(*entries,
+								      type_nsds5ReplicatedAttributeList, &attr))
+		{
+			int i;
+			const char *val = NULL;
+			for (i = slapi_attr_first_value(attr, &sval);
+				 i >= 0; i = slapi_attr_next_value(attr, i, &sval)) {
+				val = slapi_value_get_string(sval);
+				rc = agmt_parse_excluded_attrs_config_attr(val,
+														   &(ra->frac_attrs));
+				if (0 != rc) {
+					slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
+							"_agmt_set_default_fractional_attrs: failed to "
+							"parse default config (%s) attribute value: %s\n",
+							SLAPI_PLUGIN_DEFAULT_CONFIG,
+							type_nsds5ReplicatedAttributeList, val);
+				}
+			}
+		}
+	}
+
+	slapi_free_search_results_internal(newpb);
+	slapi_pblock_destroy(newpb);
+
+	return rc;
+}
+
+/*
  * Set or reset the set of replicated attributes.
  *
  * Returns 0 if DN set, or -1 if an error occurred.
@@ -1130,6 +1212,7 @@ agmt_set_replicated_attributes_from_entry(Repl_Agmt *ra, const Slapi_Entry *e)
 		slapi_ch_array_free(ra->frac_attrs);
 		ra->frac_attrs = NULL;
 	}
+	_agmt_set_default_fractional_attrs(ra);
 	if (NULL != sattr)
 	{
 		Slapi_Value *sval = NULL;
@@ -1162,6 +1245,7 @@ agmt_set_replicated_attributes_from_attr(Repl_Agmt *ra, Slapi_Attr *sattr)
 		slapi_ch_array_free(ra->frac_attrs);
 		ra->frac_attrs = NULL;
 	}
+	_agmt_set_default_fractional_attrs(ra);
 	if (NULL != sattr)
 	{
 		Slapi_Value *sval = NULL;
diff --git a/ldap/servers/plugins/usn/usn.c b/ldap/servers/plugins/usn/usn.c
index 7f46436..fd8f7c5 100644
--- a/ldap/servers/plugins/usn/usn.c
+++ b/ldap/servers/plugins/usn/usn.c
@@ -112,13 +112,13 @@ usn_init(Slapi_PBlock *pb)
     rc = slapi_register_plugin("preoperation", 1 /* Enabled */,
                                "usn_preop_init", usn_preop_init,
                                "USN preoperation plugin", NULL, identity);
-    rc = slapi_register_plugin("bepreoperation", 1 /* Enabled */,
+    rc |= slapi_register_plugin("bepreoperation", 1 /* Enabled */,
                                "usn_bepreop_init", usn_bepreop_init,
                                "USN bepreoperation plugin", NULL, identity);
-    rc = slapi_register_plugin("bepostoperation", 1 /* Enabled */,
+    rc |= slapi_register_plugin("bepostoperation", 1 /* Enabled */,
                                "usn_bepostop_init", usn_bepostop_init,
                                "USN bepostoperation plugin", NULL, identity);
-   usn_set_identity(identity);
+    usn_set_identity(identity);
 bail:
     slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
                     "<-- usn_init\n");
@@ -212,14 +212,40 @@ static int
 usn_start(Slapi_PBlock *pb)
 {
     int rc = 0;
+    Slapi_Value *value;
 
     slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM, "--> usn_start\n");
 
     rc = usn_rootdse_init();
     rc |= usn_cleanup_start(pb);
-
-    slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM, "<-- usn_start\n");
-
+    if (rc) {
+        goto bail;
+    }
+    if (0) { /* Not executed; test code for slapi_get_plugin_default_config */
+        Slapi_ValueSet *vs = NULL;
+        Slapi_Value *v = NULL;
+        int i;
+
+        slapi_get_plugin_default_config("nsds5ReplicatedAttributeList", &vs);
+        if (vs) {
+            for (i = slapi_valueset_first_value(vs, &v);
+                 i != -1;
+                 i = slapi_valueset_next_value(vs, i, &v)) {
+                slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
+                        "nsds5ReplicatedAttributeList: %s\n", 
+                        slapi_value_get_string(v));
+            }
+        }
+        slapi_valueset_free(vs);
+    }
+    /* add nsds5ReplicatedAttributeList: (objectclass=*) $ EXCLUDE entryusn 
+     * to cn=plugin default config,cn=config */
+    value = slapi_value_new_string("(objectclass=*) $ EXCLUDE entryusn");
+    rc = slapi_set_plugin_default_config("nsds5ReplicatedAttributeList", value);
+    slapi_value_free(&value);
+bail:
+    slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
+                    "<-- usn_start (rc: %d)\n", rc);
     return rc;
 }
 
@@ -547,7 +573,7 @@ usn_rootdse_search(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter,
             continue;
         }
         /* get a next USN counter from be_usn_counter; then minus 1 from it */
-        PR_snprintf(usn_berval.bv_val, USN_COUNTER_BUF_LEN, "%" NSPRIu64, 
+        PR_snprintf(usn_berval.bv_val, USN_COUNTER_BUF_LEN, "%" NSPRI64 "d", 
                                  slapi_counter_get_value(be->be_usn_counter)-1);
         usn_berval.bv_len = strlen(usn_berval.bv_val);
 
diff --git a/ldap/servers/plugins/usn/usn.h b/ldap/servers/plugins/usn/usn.h
index cf0cd18..ac9f86b 100644
--- a/ldap/servers/plugins/usn/usn.h
+++ b/ldap/servers/plugins/usn/usn.h
@@ -46,7 +46,7 @@
 #define USN_LAST_USN               "lastusn"
 #define USN_LAST_USN_ATTR_CORE_LEN 8 /* lastusn; */
 
-#define USN_COUNTER_BUF_LEN        32 /* enough size for 64 bit inteters */
+#define USN_COUNTER_BUF_LEN        64 /* enough size for 64 bit integers */
 
 /* usn.c */
 void usn_set_identity(void *identity);
diff --git a/ldap/servers/slapd/dse.c b/ldap/servers/slapd/dse.c
index 4a0312b..f0d124c 100644
--- a/ldap/servers/slapd/dse.c
+++ b/ldap/servers/slapd/dse.c
@@ -2323,15 +2323,14 @@ dse_search_set_release (void **ss)
 }
 
 void 
-dse_prev_search_results (Slapi_PBlock *pb)
+dse_prev_search_results (void *vp)
 {
+	Slapi_PBlock *pb = (Slapi_PBlock *)vp;
 	dse_search_set *ss;
-	slapi_pblock_get( pb, SLAPI_SEARCH_RESULT_SET, &ss );
+	slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &ss);
 	if (ss) {
 		dl_get_prev (&ss->dl, &ss->current_entry);
 	}
-	return;
-
 }
 
 static void 
diff --git a/ldap/servers/slapd/plugin.c b/ldap/servers/slapd/plugin.c
index e5e016d..75ec4f9 100644
--- a/ldap/servers/slapd/plugin.c
+++ b/ldap/servers/slapd/plugin.c
@@ -2837,3 +2837,159 @@ bail:
 
 	return rc;
 }
+
+/*
+ * Set given "type: attr" to the plugin default config entry
+ * (cn=plugin default config,cn=config) unless the same "type: attr" pair
+ * already exists in the entry.
+ */ 
+int
+slapi_set_plugin_default_config(const char *type, Slapi_Value *value)
+{
+    Slapi_PBlock pb;
+    Slapi_Entry **entries = NULL;
+    int rc = LDAP_SUCCESS;
+    char **search_attrs = NULL; /* used by search */
+
+    if (NULL == type || '\0' == *type || NULL == value ) { /* nothing to do */
+        return rc;
+    }
+
+    charray_add(&search_attrs, slapi_ch_strdup(type));
+
+    /* cn=plugin default config,cn=config */
+    pblock_init(&pb);
+    slapi_search_internal_set_pb(&pb,
+                    SLAPI_PLUGIN_DEFAULT_CONFIG, /* Base DN */
+                    LDAP_SCOPE_BASE,
+                    "(objectclass=*)",
+                    search_attrs, /* Attrs */
+                    0, /* AttrOnly */
+                    NULL, /* Controls */
+                    NULL, /* UniqueID */
+                    (void *)plugin_get_default_component_id(),
+                    0);
+    slapi_search_internal_pb(&pb);
+    slapi_pblock_get(&pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
+    slapi_pblock_get(&pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
+    if (LDAP_SUCCESS == rc && entries && *entries) {
+        /* plugin default config entry exists */
+        int exists = 0;
+        Slapi_Attr *attr = NULL;
+        rc = slapi_entry_attr_find(*entries, type, &attr);
+
+        if (0 == rc) { /* type exists in the entry */
+            if (0 == 
+                slapi_attr_value_find(attr, slapi_value_get_berval(value))) {
+                /* value exists in the entry; we don't have to do anything. */
+                exists = 1;
+            }
+        }
+        slapi_free_search_results_internal(&pb);
+        pblock_done(&pb);
+
+        if (!exists) {
+            /* The argument attr is not in the plugin default config.
+             * Let's add it. */
+            Slapi_Mods smods;
+            Slapi_Value *va[2];
+
+            va[0] = value;
+            va[1] = NULL;
+            slapi_mods_init(&smods, 1);
+            slapi_mods_add_mod_values(&smods, LDAP_MOD_ADD, type, va);
+    
+            pblock_init(&pb);
+            slapi_modify_internal_set_pb(&pb, SLAPI_PLUGIN_DEFAULT_CONFIG,
+                                      slapi_mods_get_ldapmods_byref(&smods),
+                                      NULL, NULL, /* UniqueID */
+                                      (void *)plugin_get_default_component_id(),
+                                      0 /* Flags */ );
+            slapi_modify_internal_pb(&pb);
+            slapi_pblock_get(&pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
+            slapi_mods_done(&smods);
+            pblock_done(&pb);
+        }
+    } else { /* cn=plugin default config does not exist. Let's add it. */
+        Slapi_Mods smods;
+        Slapi_Value *va[2];
+
+        slapi_free_search_results_internal(&pb);
+        pblock_done(&pb);
+
+        va[0] = value;
+        va[1] = NULL;
+        slapi_mods_init(&smods, 1);
+
+        slapi_mods_add_string(&smods, LDAP_MOD_ADD, "objectClass", "top");
+        slapi_mods_add_string(&smods, LDAP_MOD_ADD, "objectClass",
+                                                        "extensibleObject");
+        slapi_mods_add_mod_values(&smods, LDAP_MOD_ADD, type, va);
+
+        pblock_init(&pb);
+        slapi_add_internal_set_pb(&pb, SLAPI_PLUGIN_DEFAULT_CONFIG,
+                                  slapi_mods_get_ldapmods_byref(&smods), NULL, 
+                                  (void *)plugin_get_default_component_id(),
+                                  0 /* Flags */ );
+        slapi_add_internal_pb(&pb);
+        slapi_pblock_get(&pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
+        slapi_mods_done(&smods);
+        pblock_done(&pb);
+    }
+    charray_free(search_attrs);
+
+    return rc;
+}
+
+/*
+ * Get attribute values of given type from the plugin default config entry
+ * (cn=plugin default config,cn=config).
+ *
+ * Caller is responsible to free attrs by slapi_valueset_free.
+ */
+int
+slapi_get_plugin_default_config(char *type, Slapi_ValueSet **valueset)
+{
+    Slapi_PBlock pb;
+    Slapi_Entry **entries = NULL;
+    int rc = LDAP_PARAM_ERROR;
+    char **search_attrs = NULL; /* used by search */
+
+    if (NULL == type || '\0' == *type || NULL == valueset) { /* nothing to do */
+        return rc;
+    }
+
+    charray_add(&search_attrs, slapi_ch_strdup(type));
+
+    /* cn=plugin default config,cn=config */
+    pblock_init(&pb);
+    slapi_search_internal_set_pb(&pb,
+                    SLAPI_PLUGIN_DEFAULT_CONFIG, /* Base DN */
+                    LDAP_SCOPE_BASE,
+                    "(objectclass=*)",
+                    search_attrs, /* Attrs */
+                    0, /* AttrOnly */
+                    NULL, /* Controls */
+                    NULL, /* UniqueID */
+                    (void *)plugin_get_default_component_id(),
+                    0);
+    slapi_search_internal_pb(&pb);
+    slapi_pblock_get(&pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
+    slapi_pblock_get(&pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
+    if (LDAP_SUCCESS == rc && entries && *entries) {
+        /* default config entry exists */
+        /* retrieve attribute values from the entry */
+        Slapi_Attr *attr = NULL;
+        rc = slapi_entry_attr_find(*entries, type, &attr);
+		if (0 == rc) { /* type value exists */
+			rc = slapi_attr_get_valueset(attr, valueset);
+		} else {
+			rc = LDAP_NO_SUCH_ATTRIBUTE;
+		}
+    }
+    slapi_free_search_results_internal(&pb);
+    pblock_done(&pb);
+    charray_free(search_attrs);
+
+    return rc;
+}
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index 9c6c16e..4b1bbdf 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -604,7 +604,7 @@ void dse_unset_dont_ever_write_dse_files(void);
 int dse_next_search_entry (Slapi_PBlock *pb);
 char *dse_read_next_entry( char *buf, char **lastp );
 void dse_search_set_release (void **ss);
-void dse_prev_search_results (Slapi_PBlock *pb);
+void dse_prev_search_results (void *pb);
 
 
 /*
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index e59df68..75a2ddc 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -3637,6 +3637,29 @@ char **slapi_str2charray_ext( char *str, char *brkstr, int allow_dups );
 #endif
 #endif
 
+/**
+ * Set given "type: value" to the plugin default config entry
+ * (cn=plugin default config,cn=config) unless the same "type: value" pair
+ * already exists in the entry.
+ *
+ * \param type Attribute type to add to the default config entry
+ * \param value Attribute value to add to the default config entry
+ * \return 0 if the operation was successful
+ * \return non-0 if the operation was not successful
+ */
+int slapi_set_plugin_default_config(const char *type, Slapi_Value *value);
+
+/**
+ * Get attribute values of given type from the plugin default config entry
+ * (cn=plugin default config,cn=config).
+ *
+ * \param type Attribute type to get from the default config entry
+ * \param valueset Valueset holding the attribute values
+ * \return 0 if the operation was successful
+ * \return non-0 if the operation was not successful
+ * \warning Caller is responsible to free attrs by slapi_ch_array_free
+ *     */
+int slapi_get_plugin_default_config(char *type, Slapi_ValueSet **valueset);
 
 #ifdef __cplusplus
 }
diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
index c09e975..0f32f00 100644
--- a/ldap/servers/slapd/slapi-private.h
+++ b/ldap/servers/slapd/slapi-private.h
@@ -1177,6 +1177,8 @@ void bervalarray_add_berval_fast(struct berval ***vals, const struct berval *add
    configuration entries will be found */
 #define PLUGIN_BASE_DN "cn=plugins,cn=config"
 
+#define SLAPI_PLUGIN_DEFAULT_CONFIG   "cn=plugin default config,cn=config"
+
 /***** End of items added for the replication plugin. ***********************/
 
 void    DS_Sleep(PRIntervalTime ticks);
-- 
1.6.2.5

