ldap/servers
by Mark Reynolds
ldap/servers/slapd/daemon.c | 8 +++++---
ldap/servers/slapd/slapi-plugin.h | 5 +++++
2 files changed, 10 insertions(+), 3 deletions(-)
New commits:
commit 069657f1b3c04390c438066bd9ddc8c6a79f1dd0
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Fri Sep 27 09:20:51 2013 -0400
Ticket 47510 - 389-ds-base does not compile against MozLDAP libraries
Used #ifdef's to remove openldap specific API calls.
Thanks to mvocu for providing the initial patch.
https://fedorahosted.org/389/ticket/47510
Reviewed by: rmeggins(Thanks!)
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
index ba40f53..aed76ed 100644
--- a/ldap/servers/slapd/daemon.c
+++ b/ldap/servers/slapd/daemon.c
@@ -2541,8 +2541,9 @@ bail:
void
handle_closed_connection(Connection *conn)
{
- ber_sockbuf_remove_io(conn->c_sb, &openldap_sockbuf_io,
- LBER_SBIOD_LEVEL_PROVIDER);
+#ifdef USE_OPENLDAP
+ ber_sockbuf_remove_io(conn->c_sb, &openldap_sockbuf_io, LBER_SBIOD_LEVEL_PROVIDER);
+#endif
}
/* NOTE: this routine is not reentrant */
@@ -2628,8 +2629,9 @@ handle_new_connection(Connection_Table *ct, int tcps, PRFileDesc *pr_acceptfd, i
}
#endif /* !USE_OPENLDAP */
maxbersize = config_get_maxbersize();
+#if defined(USE_OPENLDAP)
ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &maxbersize );
-
+#endif
if( secure && config_get_SSLclientAuth() != SLAPD_SSLCLIENTAUTH_OFF ) {
/* Prepare to handle the client's certificate (if any): */
int rv;
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index f904267..659bf87 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -374,6 +374,11 @@ NSPR_API(PRUint32) PR_fprintf(struct PRFileDesc* fd, const char *fmt, ...)
#define LDAP_MAXINT (2147483647)
#endif
+/* for mozldap builds */
+#ifndef LDAP_CANCELLED
+#define LDAP_CANCELLED 0x76
+#endif
+
/*
* Sequential access types
*/
10 years, 6 months
ldap/admin ldap/ldif ldap/servers Makefile.am Makefile.in
by Ludwig Krispenz
Makefile.am | 14
Makefile.in | 103 +++-
ldap/admin/src/scripts/50contentsync.ldif | 22
ldap/ldif/template-dse.ldif.in | 21
ldap/servers/plugins/sync/sync.h | 196 ++++++++
ldap/servers/plugins/sync/sync_init.c | 174 +++++++
ldap/servers/plugins/sync/sync_persist.c | 693 ++++++++++++++++++++++++++++
ldap/servers/plugins/sync/sync_refresh.c | 732 ++++++++++++++++++++++++++++++
ldap/servers/plugins/sync/sync_util.c | 685 ++++++++++++++++++++++++++++
ldap/servers/slapd/connection.c | 7
ldap/servers/slapd/libslapd.def | 4
ldap/servers/slapd/operation.c | 58 ++
ldap/servers/slapd/plugin.c | 9
ldap/servers/slapd/proto-slap.h | 2
ldap/servers/slapd/result.c | 80 +++
ldap/servers/slapd/slapi-plugin.h | 9
16 files changed, 2799 insertions(+), 10 deletions(-)
New commits:
commit 1e7c62deba556af7f6cf30e021dc64be1ad8ccc9
Author: Ludwig Krispenz <lkrispen(a)redhat.com>
Date: Fri Sep 27 13:58:40 2013 +0200
Ticket 47388 - RFE to implement RFC4533 -ver2
Bug Description: Request to implement RFC4533 in ds 389
Fix Description: This fix impements the content synchronization as
a directory server plugin, using the retro changelog
to provide synchronization with cookies.
The design is presented here:
http://port389.org/wiki/Content_synchronization_plugin
https://fedorahosted.org/389/ticket/47388
Reviewed by: nkinder, Thanks
diff --git a/Makefile.am b/Makefile.am
index 12d4641..441fe40 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -225,6 +225,7 @@ serverplugin_LTLIBRARIES = libacl-plugin.la libattr-unique-plugin.la \
libdes-plugin.la libdistrib-plugin.la libhttp-client-plugin.la \
liblinkedattrs-plugin.la libmanagedentries-plugin.la \
libmemberof-plugin.la libpassthru-plugin.la libpwdstorage-plugin.la \
+ libcontentsync-plugin.la \
libreferint-plugin.la libreplication-plugin.la libretrocl-plugin.la \
libroles-plugin.la libstatechange-plugin.la libsyntax-plugin.la \
libviews-plugin.la libschemareload-plugin.la libusn-plugin.la \
@@ -564,6 +565,7 @@ update_DATA = ldap/admin/src/scripts/exampleupdate.pl \
ldap/admin/src/scripts/50refintprecedence.ldif \
ldap/admin/src/scripts/50retroclprecedence.ldif \
ldap/admin/src/scripts/50rootdnaccesscontrolplugin.ldif \
+ ldap/admin/src/scripts/50contentsync.ldif \
ldap/admin/src/scripts/60upgradeschemafiles.pl \
ldap/admin/src/scripts/70upgradefromldif.pl \
ldap/admin/src/scripts/80upgradednformat.pl \
@@ -1135,6 +1137,18 @@ libpwdstorage_plugin_la_LIBADD = libslapd.la $(NSS_LINK) $(NSPR_LINK) $(LIBCRYPT
libpwdstorage_plugin_la_LDFLAGS = -avoid-version
#------------------------
+# libcontentsync-plugin
+#------------------------
+libcontentsync_plugin_la_SOURCES = ldap/servers/plugins/sync/sync_init.c \
+ ldap/servers/plugins/sync/sync_util.c \
+ ldap/servers/plugins/sync/sync_refresh.c \
+ ldap/servers/plugins/sync/sync_persist.c
+
+libcontentsync_plugin_la_CPPFLAGS = $(PLUGIN_CPPFLAGS)
+libcontentsync_plugin_la_LIBADD = libslapd.la $(NSS_LINK) $(NSPR_LINK) $(LIBCRYPT)
+libcontentsync_plugin_la_LDFLAGS = -avoid-version
+
+#------------------------
# libreferint-plugin
#------------------------
libreferint_plugin_la_SOURCES = ldap/servers/plugins/referint/referint.c
diff --git a/Makefile.in b/Makefile.in
index 48444c6..9c9bcd9 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -364,6 +364,18 @@ am_libcollation_plugin_la_OBJECTS = ldap/servers/plugins/collation/libcollation_
ldap/servers/plugins/collation/libcollation_plugin_la-config.lo \
ldap/servers/plugins/collation/libcollation_plugin_la-orfilter.lo
libcollation_plugin_la_OBJECTS = $(am_libcollation_plugin_la_OBJECTS)
+libcontentsync_plugin_la_DEPENDENCIES = libslapd.la \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+am_libcontentsync_plugin_la_OBJECTS = ldap/servers/plugins/sync/libcontentsync_plugin_la-sync_init.lo \
+ ldap/servers/plugins/sync/libcontentsync_plugin_la-sync_util.lo \
+ ldap/servers/plugins/sync/libcontentsync_plugin_la-sync_refresh.lo \
+ ldap/servers/plugins/sync/libcontentsync_plugin_la-sync_persist.lo
+libcontentsync_plugin_la_OBJECTS = \
+ $(am_libcontentsync_plugin_la_OBJECTS)
+libcontentsync_plugin_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libcontentsync_plugin_la_LDFLAGS) $(LDFLAGS) -o $@
libcos_plugin_la_DEPENDENCIES = libslapd.la $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1)
am_libcos_plugin_la_OBJECTS = \
@@ -1137,9 +1149,11 @@ SOURCES = $(libavl_a_SOURCES) $(libldaputil_a_SOURCES) \
$(libautomember_plugin_la_SOURCES) $(libback_ldbm_la_SOURCES) \
$(libbitwise_plugin_la_SOURCES) \
$(libchainingdb_plugin_la_SOURCES) \
- $(libcollation_plugin_la_SOURCES) $(libcos_plugin_la_SOURCES) \
- $(libderef_plugin_la_SOURCES) $(libdes_plugin_la_SOURCES) \
- $(libdistrib_plugin_la_SOURCES) $(libdna_plugin_la_SOURCES) \
+ $(libcollation_plugin_la_SOURCES) \
+ $(libcontentsync_plugin_la_SOURCES) \
+ $(libcos_plugin_la_SOURCES) $(libderef_plugin_la_SOURCES) \
+ $(libdes_plugin_la_SOURCES) $(libdistrib_plugin_la_SOURCES) \
+ $(libdna_plugin_la_SOURCES) \
$(libhttp_client_plugin_la_SOURCES) \
$(liblinkedattrs_plugin_la_SOURCES) \
$(libmanagedentries_plugin_la_SOURCES) \
@@ -1171,9 +1185,11 @@ DIST_SOURCES = $(libavl_a_SOURCES) $(libldaputil_a_SOURCES) \
$(libautomember_plugin_la_SOURCES) $(libback_ldbm_la_SOURCES) \
$(libbitwise_plugin_la_SOURCES) \
$(libchainingdb_plugin_la_SOURCES) \
- $(libcollation_plugin_la_SOURCES) $(libcos_plugin_la_SOURCES) \
- $(libderef_plugin_la_SOURCES) $(libdes_plugin_la_SOURCES) \
- $(libdistrib_plugin_la_SOURCES) $(libdna_plugin_la_SOURCES) \
+ $(libcollation_plugin_la_SOURCES) \
+ $(libcontentsync_plugin_la_SOURCES) \
+ $(libcos_plugin_la_SOURCES) $(libderef_plugin_la_SOURCES) \
+ $(libdes_plugin_la_SOURCES) $(libdistrib_plugin_la_SOURCES) \
+ $(libdna_plugin_la_SOURCES) \
$(libhttp_client_plugin_la_SOURCES) \
$(liblinkedattrs_plugin_la_SOURCES) \
$(libmanagedentries_plugin_la_SOURCES) \
@@ -1619,6 +1635,7 @@ serverplugin_LTLIBRARIES = libacl-plugin.la libattr-unique-plugin.la \
libdes-plugin.la libdistrib-plugin.la libhttp-client-plugin.la \
liblinkedattrs-plugin.la libmanagedentries-plugin.la \
libmemberof-plugin.la libpassthru-plugin.la libpwdstorage-plugin.la \
+ libcontentsync-plugin.la \
libreferint-plugin.la libreplication-plugin.la libretrocl-plugin.la \
libroles-plugin.la libstatechange-plugin.la libsyntax-plugin.la \
libviews-plugin.la libschemareload-plugin.la libusn-plugin.la \
@@ -1954,6 +1971,7 @@ update_DATA = ldap/admin/src/scripts/exampleupdate.pl \
ldap/admin/src/scripts/50refintprecedence.ldif \
ldap/admin/src/scripts/50retroclprecedence.ldif \
ldap/admin/src/scripts/50rootdnaccesscontrolplugin.ldif \
+ ldap/admin/src/scripts/50contentsync.ldif \
ldap/admin/src/scripts/60upgradeschemafiles.pl \
ldap/admin/src/scripts/70upgradefromldif.pl \
ldap/admin/src/scripts/80upgradednformat.pl \
@@ -2461,6 +2479,18 @@ libpwdstorage_plugin_la_LIBADD = libslapd.la $(NSS_LINK) $(NSPR_LINK) $(LIBCRYPT
libpwdstorage_plugin_la_LDFLAGS = -avoid-version
#------------------------
+# libcontentsync-plugin
+#------------------------
+libcontentsync_plugin_la_SOURCES = ldap/servers/plugins/sync/sync_init.c \
+ ldap/servers/plugins/sync/sync_util.c \
+ ldap/servers/plugins/sync/sync_refresh.c \
+ ldap/servers/plugins/sync/sync_persist.c
+
+libcontentsync_plugin_la_CPPFLAGS = $(PLUGIN_CPPFLAGS)
+libcontentsync_plugin_la_LIBADD = libslapd.la $(NSS_LINK) $(NSPR_LINK) $(LIBCRYPT)
+libcontentsync_plugin_la_LDFLAGS = -avoid-version
+
+#------------------------
# libreferint-plugin
#------------------------
libreferint_plugin_la_SOURCES = ldap/servers/plugins/referint/referint.c
@@ -3504,6 +3534,26 @@ ldap/servers/plugins/collation/libcollation_plugin_la-orfilter.lo: \
libcollation-plugin.la: $(libcollation_plugin_la_OBJECTS) $(libcollation_plugin_la_DEPENDENCIES) $(EXTRA_libcollation_plugin_la_DEPENDENCIES)
$(AM_V_GEN)$(libcollation_plugin_la_LINK) -rpath $(serverplugindir) $(libcollation_plugin_la_OBJECTS) $(libcollation_plugin_la_LIBADD) $(LIBS)
+ldap/servers/plugins/sync/$(am__dirstamp):
+ @$(MKDIR_P) ldap/servers/plugins/sync
+ @: > ldap/servers/plugins/sync/$(am__dirstamp)
+ldap/servers/plugins/sync/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) ldap/servers/plugins/sync/$(DEPDIR)
+ @: > ldap/servers/plugins/sync/$(DEPDIR)/$(am__dirstamp)
+ldap/servers/plugins/sync/libcontentsync_plugin_la-sync_init.lo: \
+ ldap/servers/plugins/sync/$(am__dirstamp) \
+ ldap/servers/plugins/sync/$(DEPDIR)/$(am__dirstamp)
+ldap/servers/plugins/sync/libcontentsync_plugin_la-sync_util.lo: \
+ ldap/servers/plugins/sync/$(am__dirstamp) \
+ ldap/servers/plugins/sync/$(DEPDIR)/$(am__dirstamp)
+ldap/servers/plugins/sync/libcontentsync_plugin_la-sync_refresh.lo: \
+ ldap/servers/plugins/sync/$(am__dirstamp) \
+ ldap/servers/plugins/sync/$(DEPDIR)/$(am__dirstamp)
+ldap/servers/plugins/sync/libcontentsync_plugin_la-sync_persist.lo: \
+ ldap/servers/plugins/sync/$(am__dirstamp) \
+ ldap/servers/plugins/sync/$(DEPDIR)/$(am__dirstamp)
+libcontentsync-plugin.la: $(libcontentsync_plugin_la_OBJECTS) $(libcontentsync_plugin_la_DEPENDENCIES) $(EXTRA_libcontentsync_plugin_la_DEPENDENCIES)
+ $(libcontentsync_plugin_la_LINK) -rpath $(serverplugindir) $(libcontentsync_plugin_la_OBJECTS) $(libcontentsync_plugin_la_LIBADD) $(LIBS)
ldap/servers/plugins/cos/$(am__dirstamp):
@$(MKDIR_P) ldap/servers/plugins/cos
@: > ldap/servers/plugins/cos/$(am__dirstamp)
@@ -5193,6 +5243,8 @@ mostlyclean-compile:
-rm -f ldap/servers/plugins/schema_reload/*.lo
-rm -f ldap/servers/plugins/statechange/*.$(OBJEXT)
-rm -f ldap/servers/plugins/statechange/*.lo
+ -rm -f ldap/servers/plugins/sync/*.$(OBJEXT)
+ -rm -f ldap/servers/plugins/sync/*.lo
-rm -f ldap/servers/plugins/syntaxes/*.$(OBJEXT)
-rm -f ldap/servers/plugins/syntaxes/*.lo
-rm -f ldap/servers/plugins/uiduniq/*.$(OBJEXT)
@@ -5381,6 +5433,10 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/rootdn_access/$(DEPDIR)/librootdn_access_plugin_la-rootdn_access.Plo(a)am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/schema_reload/$(DEPDIR)/libschemareload_plugin_la-schema_reload.Plo(a)am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/statechange/$(DEPDIR)/libstatechange_plugin_la-statechange.Plo(a)am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/sync/$(DEPDIR)/libcontentsync_plugin_la-sync_init.Plo(a)am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/sync/$(DEPDIR)/libcontentsync_plugin_la-sync_persist.Plo(a)am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/sync/$(DEPDIR)/libcontentsync_plugin_la-sync_refresh.Plo(a)am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/sync/$(DEPDIR)/libcontentsync_plugin_la-sync_util.Plo(a)am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/syntaxes/$(DEPDIR)/libsyntax_plugin_la-bin.Plo(a)am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/syntaxes/$(DEPDIR)/libsyntax_plugin_la-bitstring.Plo(a)am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/syntaxes/$(DEPDIR)/libsyntax_plugin_la-ces.Plo(a)am__quote@
@@ -6619,6 +6675,34 @@ ldap/servers/plugins/collation/libcollation_plugin_la-orfilter.lo: ldap/servers/
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcollation_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ldap/servers/plugins/collation/libcollation_plugin_la-orfilter.lo `test -f 'ldap/servers/plugins/collation/orfilter.c' || echo '$(srcdir)/'`ldap/servers/plugins/collation/orfilter.c
+ldap/servers/plugins/sync/libcontentsync_plugin_la-sync_init.lo: ldap/servers/plugins/sync/sync_init.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcontentsync_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ldap/servers/plugins/sync/libcontentsync_plugin_la-sync_init.lo -MD -MP -MF ldap/servers/plugins/sync/$(DEPDIR)/libcontentsync_plugin_la-sync_init.Tpo -c -o ldap/servers/plugins/sync/libcontentsync_plugin_la-sync_init.lo `test -f 'ldap/servers/plugins/sync/sync_init.c' || echo '$(srcdir)/'`ldap/servers/plugins/sync/sync_init.c
+@am__fastdepCC_TRUE@ $(am__mv) ldap/servers/plugins/sync/$(DEPDIR)/libcontentsync_plugin_la-sync_init.Tpo ldap/servers/plugins/sync/$(DEPDIR)/libcontentsync_plugin_la-sync_init.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ldap/servers/plugins/sync/sync_init.c' object='ldap/servers/plugins/sync/libcontentsync_plugin_la-sync_init.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcontentsync_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ldap/servers/plugins/sync/libcontentsync_plugin_la-sync_init.lo `test -f 'ldap/servers/plugins/sync/sync_init.c' || echo '$(srcdir)/'`ldap/servers/plugins/sync/sync_init.c
+
+ldap/servers/plugins/sync/libcontentsync_plugin_la-sync_util.lo: ldap/servers/plugins/sync/sync_util.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcontentsync_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ldap/servers/plugins/sync/libcontentsync_plugin_la-sync_util.lo -MD -MP -MF ldap/servers/plugins/sync/$(DEPDIR)/libcontentsync_plugin_la-sync_util.Tpo -c -o ldap/servers/plugins/sync/libcontentsync_plugin_la-sync_util.lo `test -f 'ldap/servers/plugins/sync/sync_util.c' || echo '$(srcdir)/'`ldap/servers/plugins/sync/sync_util.c
+@am__fastdepCC_TRUE@ $(am__mv) ldap/servers/plugins/sync/$(DEPDIR)/libcontentsync_plugin_la-sync_util.Tpo ldap/servers/plugins/sync/$(DEPDIR)/libcontentsync_plugin_la-sync_util.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ldap/servers/plugins/sync/sync_util.c' object='ldap/servers/plugins/sync/libcontentsync_plugin_la-sync_util.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcontentsync_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ldap/servers/plugins/sync/libcontentsync_plugin_la-sync_util.lo `test -f 'ldap/servers/plugins/sync/sync_util.c' || echo '$(srcdir)/'`ldap/servers/plugins/sync/sync_util.c
+
+ldap/servers/plugins/sync/libcontentsync_plugin_la-sync_refresh.lo: ldap/servers/plugins/sync/sync_refresh.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcontentsync_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ldap/servers/plugins/sync/libcontentsync_plugin_la-sync_refresh.lo -MD -MP -MF ldap/servers/plugins/sync/$(DEPDIR)/libcontentsync_plugin_la-sync_refresh.Tpo -c -o ldap/servers/plugins/sync/libcontentsync_plugin_la-sync_refresh.lo `test -f 'ldap/servers/plugins/sync/sync_refresh.c' || echo '$(srcdir)/'`ldap/servers/plugins/sync/sync_refresh.c
+@am__fastdepCC_TRUE@ $(am__mv) ldap/servers/plugins/sync/$(DEPDIR)/libcontentsync_plugin_la-sync_refresh.Tpo ldap/servers/plugins/sync/$(DEPDIR)/libcontentsync_plugin_la-sync_refresh.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ldap/servers/plugins/sync/sync_refresh.c' object='ldap/servers/plugins/sync/libcontentsync_plugin_la-sync_refresh.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcontentsync_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ldap/servers/plugins/sync/libcontentsync_plugin_la-sync_refresh.lo `test -f 'ldap/servers/plugins/sync/sync_refresh.c' || echo '$(srcdir)/'`ldap/servers/plugins/sync/sync_refresh.c
+
+ldap/servers/plugins/sync/libcontentsync_plugin_la-sync_persist.lo: ldap/servers/plugins/sync/sync_persist.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcontentsync_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ldap/servers/plugins/sync/libcontentsync_plugin_la-sync_persist.lo -MD -MP -MF ldap/servers/plugins/sync/$(DEPDIR)/libcontentsync_plugin_la-sync_persist.Tpo -c -o ldap/servers/plugins/sync/libcontentsync_plugin_la-sync_persist.lo `test -f 'ldap/servers/plugins/sync/sync_persist.c' || echo '$(srcdir)/'`ldap/servers/plugins/sync/sync_persist.c
+@am__fastdepCC_TRUE@ $(am__mv) ldap/servers/plugins/sync/$(DEPDIR)/libcontentsync_plugin_la-sync_persist.Tpo ldap/servers/plugins/sync/$(DEPDIR)/libcontentsync_plugin_la-sync_persist.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ldap/servers/plugins/sync/sync_persist.c' object='ldap/servers/plugins/sync/libcontentsync_plugin_la-sync_persist.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcontentsync_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ldap/servers/plugins/sync/libcontentsync_plugin_la-sync_persist.lo `test -f 'ldap/servers/plugins/sync/sync_persist.c' || echo '$(srcdir)/'`ldap/servers/plugins/sync/sync_persist.c
+
ldap/servers/plugins/cos/libcos_plugin_la-cos.lo: ldap/servers/plugins/cos/cos.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcos_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ldap/servers/plugins/cos/libcos_plugin_la-cos.lo -MD -MP -MF ldap/servers/plugins/cos/$(DEPDIR)/libcos_plugin_la-cos.Tpo -c -o ldap/servers/plugins/cos/libcos_plugin_la-cos.lo `test -f 'ldap/servers/plugins/cos/cos.c' || echo '$(srcdir)/'`ldap/servers/plugins/cos/cos.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ldap/servers/plugins/cos/$(DEPDIR)/libcos_plugin_la-cos.Tpo ldap/servers/plugins/cos/$(DEPDIR)/libcos_plugin_la-cos.Plo
@@ -9491,6 +9575,7 @@ clean-libtool:
-rm -rf ldap/servers/plugins/rootdn_access/.libs ldap/servers/plugins/rootdn_access/_libs
-rm -rf ldap/servers/plugins/schema_reload/.libs ldap/servers/plugins/schema_reload/_libs
-rm -rf ldap/servers/plugins/statechange/.libs ldap/servers/plugins/statechange/_libs
+ -rm -rf ldap/servers/plugins/sync/.libs ldap/servers/plugins/sync/_libs
-rm -rf ldap/servers/plugins/syntaxes/.libs ldap/servers/plugins/syntaxes/_libs
-rm -rf ldap/servers/plugins/uiduniq/.libs ldap/servers/plugins/uiduniq/_libs
-rm -rf ldap/servers/plugins/usn/.libs ldap/servers/plugins/usn/_libs
@@ -10175,6 +10260,8 @@ distclean-generic:
-rm -f ldap/servers/plugins/schema_reload/$(am__dirstamp)
-rm -f ldap/servers/plugins/statechange/$(DEPDIR)/$(am__dirstamp)
-rm -f ldap/servers/plugins/statechange/$(am__dirstamp)
+ -rm -f ldap/servers/plugins/sync/$(DEPDIR)/$(am__dirstamp)
+ -rm -f ldap/servers/plugins/sync/$(am__dirstamp)
-rm -f ldap/servers/plugins/syntaxes/$(DEPDIR)/$(am__dirstamp)
-rm -f ldap/servers/plugins/syntaxes/$(am__dirstamp)
-rm -f ldap/servers/plugins/uiduniq/$(DEPDIR)/$(am__dirstamp)
@@ -10223,7 +10310,7 @@ clean-am: clean-binPROGRAMS clean-generic clean-libtool clean-local \
distclean: distclean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
- -rm -rf ldap/libraries/libavl/$(DEPDIR) ldap/servers/plugins/acct_usability/$(DEPDIR) ldap/servers/plugins/acctpolicy/$(DEPDIR) ldap/servers/plugins/acl/$(DEPDIR) ldap/servers/plugins/automember/$(DEPDIR) ldap/servers/plugins/bitwise/$(DEPDIR) ldap/servers/plugins/chainingdb/$(DEPDIR) ldap/servers/plugins/collation/$(DEPDIR) ldap/servers/plugins/cos/$(DEPDIR) ldap/servers/plugins/deref/$(DEPDIR) ldap/servers/plugins/distrib/$(DEPDIR) ldap/servers/plugins/dna/$(DEPDIR) ldap/servers/plugins/http/$(DEPDIR) ldap/servers/plugins/linkedattrs/$(DEPDIR) ldap/servers/plugins/memberof/$(DEPDIR) ldap/servers/plugins/mep/$(DEPDIR) ldap/servers/plugins/pam_passthru/$(DEPDIR) ldap/servers/plugins/passthru/$(DEPDIR) ldap/servers/plugins/posix-winsync/$(DEPDIR) ldap/servers/plugins/presence/$(DEPDIR) ldap/servers/plugins/pwdstorage/$(DEPDIR) ldap/servers/plugins/referint/$(DEPDIR) ldap/servers/plugins/replication/$(DEPDIR) ldap/servers/plugins/retrocl/$(DEPDIR) ldap/servers/plugins/rever/$
(DEPDIR) ldap/servers/plugins/roles/$(DEPDIR) ldap/servers/plugins/rootdn_access/$(DEPDIR) ldap/servers/plugins/schema_reload/$(DEPDIR) ldap/servers/plugins/statechange/$(DEPDIR) ldap/servers/plugins/syntaxes/$(DEPDIR) ldap/servers/plugins/uiduniq/$(DEPDIR) ldap/servers/plugins/usn/$(DEPDIR) ldap/servers/plugins/views/$(DEPDIR) ldap/servers/plugins/whoami/$(DEPDIR) ldap/servers/slapd/$(DEPDIR) ldap/servers/slapd/back-ldbm/$(DEPDIR) ldap/servers/slapd/tools/$(DEPDIR) ldap/servers/slapd/tools/ldclt/$(DEPDIR) ldap/servers/slapd/tools/rsearch/$(DEPDIR) ldap/servers/snmp/$(DEPDIR) ldap/systools/$(DEPDIR) lib/base/$(DEPDIR) lib/ldaputil/$(DEPDIR) lib/libaccess/$(DEPDIR) lib/libadmin/$(DEPDIR) lib/libsi18n/$(DEPDIR)
+ -rm -rf ldap/libraries/libavl/$(DEPDIR) ldap/servers/plugins/acct_usability/$(DEPDIR) ldap/servers/plugins/acctpolicy/$(DEPDIR) ldap/servers/plugins/acl/$(DEPDIR) ldap/servers/plugins/automember/$(DEPDIR) ldap/servers/plugins/bitwise/$(DEPDIR) ldap/servers/plugins/chainingdb/$(DEPDIR) ldap/servers/plugins/collation/$(DEPDIR) ldap/servers/plugins/cos/$(DEPDIR) ldap/servers/plugins/deref/$(DEPDIR) ldap/servers/plugins/distrib/$(DEPDIR) ldap/servers/plugins/dna/$(DEPDIR) ldap/servers/plugins/http/$(DEPDIR) ldap/servers/plugins/linkedattrs/$(DEPDIR) ldap/servers/plugins/memberof/$(DEPDIR) ldap/servers/plugins/mep/$(DEPDIR) ldap/servers/plugins/pam_passthru/$(DEPDIR) ldap/servers/plugins/passthru/$(DEPDIR) ldap/servers/plugins/posix-winsync/$(DEPDIR) ldap/servers/plugins/presence/$(DEPDIR) ldap/servers/plugins/pwdstorage/$(DEPDIR) ldap/servers/plugins/referint/$(DEPDIR) ldap/servers/plugins/replication/$(DEPDIR) ldap/servers/plugins/retrocl/$(DEPDIR) ldap/servers/plugins/rever/$
(DEPDIR) ldap/servers/plugins/roles/$(DEPDIR) ldap/servers/plugins/rootdn_access/$(DEPDIR) ldap/servers/plugins/schema_reload/$(DEPDIR) ldap/servers/plugins/statechange/$(DEPDIR) ldap/servers/plugins/sync/$(DEPDIR) ldap/servers/plugins/syntaxes/$(DEPDIR) ldap/servers/plugins/uiduniq/$(DEPDIR) ldap/servers/plugins/usn/$(DEPDIR) ldap/servers/plugins/views/$(DEPDIR) ldap/servers/plugins/whoami/$(DEPDIR) ldap/servers/slapd/$(DEPDIR) ldap/servers/slapd/back-ldbm/$(DEPDIR) ldap/servers/slapd/tools/$(DEPDIR) ldap/servers/slapd/tools/ldclt/$(DEPDIR) ldap/servers/slapd/tools/rsearch/$(DEPDIR) ldap/servers/snmp/$(DEPDIR) ldap/systools/$(DEPDIR) lib/base/$(DEPDIR) lib/ldaputil/$(DEPDIR) lib/libaccess/$(DEPDIR) lib/libadmin/$(DEPDIR) lib/libsi18n/$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-hdr distclean-libtool distclean-tags
@@ -10279,7 +10366,7 @@ installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf $(top_srcdir)/autom4te.cache
- -rm -rf ldap/libraries/libavl/$(DEPDIR) ldap/servers/plugins/acct_usability/$(DEPDIR) ldap/servers/plugins/acctpolicy/$(DEPDIR) ldap/servers/plugins/acl/$(DEPDIR) ldap/servers/plugins/automember/$(DEPDIR) ldap/servers/plugins/bitwise/$(DEPDIR) ldap/servers/plugins/chainingdb/$(DEPDIR) ldap/servers/plugins/collation/$(DEPDIR) ldap/servers/plugins/cos/$(DEPDIR) ldap/servers/plugins/deref/$(DEPDIR) ldap/servers/plugins/distrib/$(DEPDIR) ldap/servers/plugins/dna/$(DEPDIR) ldap/servers/plugins/http/$(DEPDIR) ldap/servers/plugins/linkedattrs/$(DEPDIR) ldap/servers/plugins/memberof/$(DEPDIR) ldap/servers/plugins/mep/$(DEPDIR) ldap/servers/plugins/pam_passthru/$(DEPDIR) ldap/servers/plugins/passthru/$(DEPDIR) ldap/servers/plugins/posix-winsync/$(DEPDIR) ldap/servers/plugins/presence/$(DEPDIR) ldap/servers/plugins/pwdstorage/$(DEPDIR) ldap/servers/plugins/referint/$(DEPDIR) ldap/servers/plugins/replication/$(DEPDIR) ldap/servers/plugins/retrocl/$(DEPDIR) ldap/servers/plugins/rever/$
(DEPDIR) ldap/servers/plugins/roles/$(DEPDIR) ldap/servers/plugins/rootdn_access/$(DEPDIR) ldap/servers/plugins/schema_reload/$(DEPDIR) ldap/servers/plugins/statechange/$(DEPDIR) ldap/servers/plugins/syntaxes/$(DEPDIR) ldap/servers/plugins/uiduniq/$(DEPDIR) ldap/servers/plugins/usn/$(DEPDIR) ldap/servers/plugins/views/$(DEPDIR) ldap/servers/plugins/whoami/$(DEPDIR) ldap/servers/slapd/$(DEPDIR) ldap/servers/slapd/back-ldbm/$(DEPDIR) ldap/servers/slapd/tools/$(DEPDIR) ldap/servers/slapd/tools/ldclt/$(DEPDIR) ldap/servers/slapd/tools/rsearch/$(DEPDIR) ldap/servers/snmp/$(DEPDIR) ldap/systools/$(DEPDIR) lib/base/$(DEPDIR) lib/ldaputil/$(DEPDIR) lib/libaccess/$(DEPDIR) lib/libadmin/$(DEPDIR) lib/libsi18n/$(DEPDIR)
+ -rm -rf ldap/libraries/libavl/$(DEPDIR) ldap/servers/plugins/acct_usability/$(DEPDIR) ldap/servers/plugins/acctpolicy/$(DEPDIR) ldap/servers/plugins/acl/$(DEPDIR) ldap/servers/plugins/automember/$(DEPDIR) ldap/servers/plugins/bitwise/$(DEPDIR) ldap/servers/plugins/chainingdb/$(DEPDIR) ldap/servers/plugins/collation/$(DEPDIR) ldap/servers/plugins/cos/$(DEPDIR) ldap/servers/plugins/deref/$(DEPDIR) ldap/servers/plugins/distrib/$(DEPDIR) ldap/servers/plugins/dna/$(DEPDIR) ldap/servers/plugins/http/$(DEPDIR) ldap/servers/plugins/linkedattrs/$(DEPDIR) ldap/servers/plugins/memberof/$(DEPDIR) ldap/servers/plugins/mep/$(DEPDIR) ldap/servers/plugins/pam_passthru/$(DEPDIR) ldap/servers/plugins/passthru/$(DEPDIR) ldap/servers/plugins/posix-winsync/$(DEPDIR) ldap/servers/plugins/presence/$(DEPDIR) ldap/servers/plugins/pwdstorage/$(DEPDIR) ldap/servers/plugins/referint/$(DEPDIR) ldap/servers/plugins/replication/$(DEPDIR) ldap/servers/plugins/retrocl/$(DEPDIR) ldap/servers/plugins/rever/$
(DEPDIR) ldap/servers/plugins/roles/$(DEPDIR) ldap/servers/plugins/rootdn_access/$(DEPDIR) ldap/servers/plugins/schema_reload/$(DEPDIR) ldap/servers/plugins/statechange/$(DEPDIR) ldap/servers/plugins/sync/$(DEPDIR) ldap/servers/plugins/syntaxes/$(DEPDIR) ldap/servers/plugins/uiduniq/$(DEPDIR) ldap/servers/plugins/usn/$(DEPDIR) ldap/servers/plugins/views/$(DEPDIR) ldap/servers/plugins/whoami/$(DEPDIR) ldap/servers/slapd/$(DEPDIR) ldap/servers/slapd/back-ldbm/$(DEPDIR) ldap/servers/slapd/tools/$(DEPDIR) ldap/servers/slapd/tools/ldclt/$(DEPDIR) ldap/servers/slapd/tools/rsearch/$(DEPDIR) ldap/servers/snmp/$(DEPDIR) ldap/systools/$(DEPDIR) lib/base/$(DEPDIR) lib/ldaputil/$(DEPDIR) lib/libaccess/$(DEPDIR) lib/libadmin/$(DEPDIR) lib/libsi18n/$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
diff --git a/ldap/admin/src/scripts/50contentsync.ldif b/ldap/admin/src/scripts/50contentsync.ldif
new file mode 100644
index 0000000..0f15bdb
--- /dev/null
+++ b/ldap/admin/src/scripts/50contentsync.ldif
@@ -0,0 +1,22 @@
+dn: cn=Content Synchronization,cn=plugins,cn=config
+objectclass: top
+objectclass: nsSlapdPlugin
+cn: Content Synchronization
+nsslapd-pluginpath: libcontentsync-plugin
+nsslapd-plugininitfunc: sync_init
+nsslapd-plugintype: object
+nsslapd-pluginenabled: off
+nsslapd-plugin-depends-on-named: Retro Changelog Plugin
+# these will be replaced when the server loads the plugin
+nsslapd-pluginId: ID
+nsslapd-pluginVersion: PACKAGE_VERSION
+nsslapd-pluginVendor: VENDOR
+nsslapd-pluginDescription: DESC
+
+dn: oid=1.3.6.1.4.1.4203.1.9.1.1,cn=features,cn=config
+objectClass: top
+objectClass: directoryServerFeature
+oid: 1.3.6.1.4.1.4203.1.9.1.1
+cn: Sync Request Control
+aci: (targetattr != "aci")(version 3.0; acl "Sync Request Control"; allow( read
+ , search ) userdn = "ldap:///all";)
diff --git a/ldap/ldif/template-dse.ldif.in b/ldap/ldif/template-dse.ldif.in
index 189c4aa..084aacb 100644
--- a/ldap/ldif/template-dse.ldif.in
+++ b/ldap/ldif/template-dse.ldif.in
@@ -70,6 +70,14 @@ objectClass: directoryServerFeature
oid: 1.3.6.1.4.1.42.2.27.9.5.8
cn: Account Usable Request Control
+dn: oid=1.3.6.1.4.1.4203.1.9.1.1,cn=features,cn=config
+objectClass: top
+objectClass: directoryServerFeature
+oid: 1.3.6.1.4.1.4203.1.9.1.1
+cn: Sync Request Control
+aci: (targetattr != "aci")(version 3.0; acl "Sync Request Control"; allow( read
+ , search ) userdn = "ldap:///all";)
+
dn: cn=plugins,cn=config
objectclass: top
objectclass: nsContainer
@@ -656,6 +664,19 @@ nsslapd-plugintype: betxnpreoperation
nsslapd-pluginenabled: on
nsslapd-plugin-depends-on-type: database
+dn: cn=Content Synchronization,cn=plugins,cn=config
+objectclass: top
+objectclass: nsSlapdPlugin
+objectclass: extensibleObject
+cn: Content Synchronization
+nsslapd-pluginpath: libcontentsync-plugin
+nsslapd-plugininitfunc: sync_init
+nsslapd-plugintype: object
+nsslapd-pluginenabled: off
+nsslapd-pluginbetxn: on
+nsslapd-plugin-depends-on-type: database
+nsslapd-plugin-depends-on-named: Retro Changelog Plugin
+
dn: cn=deref,cn=plugins,cn=config
objectclass: top
objectclass: nsSlapdPlugin
diff --git a/ldap/servers/plugins/sync/sync.h b/ldap/servers/plugins/sync/sync.h
new file mode 100644
index 0000000..cf73ce9
--- /dev/null
+++ b/ldap/servers/plugins/sync/sync.h
@@ -0,0 +1,196 @@
+/** BEGIN COPYRIGHT BLOCK
+ * This Program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; version 2 of the License.
+ *
+ * This Program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception.
+ *
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/**
+ * LDAP content synchronization plug-in
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "slapi-plugin.h"
+
+#define PLUGIN_NAME "content-sync-plugin"
+
+#define SYNC_PLUGIN_SUBSYSTEM "content-sync-plugin"
+#define SYNC_PREOP_DESC "content-sync-preop-subplugin"
+#define SYNC_POSTOP_DESC "content-sync-postop-subplugin"
+
+#define OP_FLAG_SYNC_PERSIST 0x01
+
+#define E_SYNC_REFRESH_REQUIRED 0x1000
+
+#define CL_ATTR_CHANGENUMBER "changenumber"
+#define CL_ATTR_ENTRYDN "targetDn"
+#define CL_ATTR_UNIQUEID "targetUniqueId"
+#define CL_ATTR_CHGTYPE "changetype"
+#define CL_ATTR_NEWSUPERIOR "newsuperior"
+#define CL_SRCH_BASE "cn=changelog"
+
+typedef struct sync_cookie {
+ char *cookie_client_signature;
+ char *cookie_server_signature;
+ int cookie_change_info;
+} Sync_Cookie;
+
+typedef struct sync_update {
+ char *upd_uuid;
+ int upd_chgtype;
+ Slapi_Entry *upd_e;
+} Sync_UpdateNode;
+
+typedef struct sync_callback {
+ Slapi_PBlock *orig_pb;
+ int changenr;
+ int change_start;
+ int cb_err;
+ Sync_UpdateNode *cb_updates;
+} Sync_CallBackData;
+
+int sync_register_operation_extension(void);
+
+int sync_srch_refresh_pre_search(Slapi_PBlock *pb);
+int sync_srch_refresh_post_search(Slapi_PBlock *pb);
+int sync_srch_refresh_pre_entry(Slapi_PBlock *pb);
+int sync_srch_refresh_pre_result(Slapi_PBlock *pb);
+int sync_del_persist_post_op(Slapi_PBlock *pb);
+int sync_mod_persist_post_op(Slapi_PBlock *pb);
+int sync_modrdn_persist_post_op(Slapi_PBlock *pb);
+int sync_add_persist_post_op(Slapi_PBlock *pb);
+
+int sync_parse_control_value( struct berval *psbvp, ber_int_t *mode, int *reload, char **cookie );
+int sync_create_state_control( Slapi_Entry *e, LDAPControl **ctrlp, int type, Sync_Cookie *cookie);
+int sync_create_sync_done_control( LDAPControl **ctrlp, int refresh, char *cookie);
+int sync_intermediate_msg (Slapi_PBlock *pb, int tag, Sync_Cookie *cookie, char **uuids);
+int sync_result_msg (Slapi_PBlock *pb, Sync_Cookie *cookie);
+int sync_result_err (Slapi_PBlock *pb, int rc, char *msg);
+
+Sync_Cookie *sync_cookie_create (Slapi_PBlock *pb);
+void sync_cookie_update (Sync_Cookie *cookie, Slapi_Entry *ec);
+Sync_Cookie *sync_cookie_parse (char *cookie);
+int sync_cookie_isvalid (Sync_Cookie *testcookie, Sync_Cookie *refcookie);
+void sync_cookie_free (Sync_Cookie **freecookie);
+char * sync_cookie2str(Sync_Cookie *cookie);
+int sync_number2int(char *nrstr);
+char *sync_nsuniqueid2uuid(const char *nsuniqueid);
+
+int sync_is_active (Slapi_Entry *e, Slapi_PBlock *pb);
+int sync_is_active_scope (const Slapi_DN *dn, Slapi_PBlock *pb);
+
+int sync_refresh_update_content(Slapi_PBlock *pb, Sync_Cookie *client_cookie, Sync_Cookie *session_cookie);
+int sync_refresh_initial_content(Slapi_PBlock *pb, int persist, Sync_Cookie *session_cookie);
+int sync_read_entry_from_changelog( Slapi_Entry *cl_entry, void *cb_data);
+int sync_send_entry_from_changelog( Slapi_PBlock *pb, int chg_req, char *uniqueid);
+void sync_send_deleted_entries (Slapi_PBlock *pb, Sync_UpdateNode *upd, int chg_count, Sync_Cookie *session_cookie);
+void sync_send_modified_entries (Slapi_PBlock *pb, Sync_UpdateNode *upd, int chg_count);
+
+int sync_persist_initialize (int argc, char **argv);
+PRThread *sync_persist_add (Slapi_PBlock *pb);
+int sync_persist_startup (PRThread *tid, Sync_Cookie *session_cookie);
+int sync_persist_terminate_all ();
+int sync_persist_terminate (PRThread *tid);
+
+Slapi_PBlock *sync_pblock_copy(Slapi_PBlock *src);
+
+/* prototype for functions not in slapi-plugin.h */
+Slapi_ComponentId *plugin_get_default_component_id();
+
+
+/*
+ * Structures to handle the persitent phase of
+ * Content Synchronization Requests
+ *
+ * A queue of entries being to be sent by a particular persistent
+ * sync thread
+ *
+ * will be created in post op plugins
+ */
+typedef struct sync_queue_node {
+ Slapi_Entry *sync_entry;
+ LDAPControl *pe_ctrls[2]; /* XXX ?? XXX */
+ struct sync_queue_node *sync_next;
+ int sync_chgtype;
+} SyncQueueNode;
+
+/*
+ * Information about a single sync search
+ *
+ * will be created when a content sync control with
+ * mode == 3 is decoded
+ */
+typedef struct sync_request {
+ Slapi_PBlock *req_pblock;
+ PRLock *req_lock;
+ PRThread *req_tid;
+ char *req_orig_base;
+ Slapi_Filter *req_filter;
+ PRInt32 req_complete;
+ Sync_Cookie *req_cookie;
+ SyncQueueNode *ps_eq_head;
+ SyncQueueNode *ps_eq_tail;
+ int req_active;
+ struct sync_request *req_next;
+} SyncRequest;
+
+/*
+ * A list of established persistent synchronization searches.
+ *
+ * will be initialized at plugin initialization
+ */
+#define SYNC_MAX_CONCURRENT 10
+typedef struct sync_request_list {
+ Slapi_RWLock *sync_req_rwlock; /* R/W lock struct to serialize access */
+ SyncRequest *sync_req_head; /* Head of list */
+ PRLock *sync_req_cvarlock; /* Lock for cvar */
+ PRCondVar *sync_req_cvar; /* ps threads sleep on this */
+ int sync_req_max_persist;
+ int sync_req_cur_persist;
+} SyncRequestList;
+
+#define SYNC_FLAG_ADD_STATE_CTRL 0x01
+#define SYNC_FLAG_ADD_DONE_CTRL 0x02
+#define SYNC_FLAG_NO_RESULT 0x04
+#define SYNC_FLAG_SEND_INTERMEDIATE 0x08
+
+typedef struct sync_op_info {
+ int send_flag; /* hint for preop plugins what to send */
+ Sync_Cookie *cookie; /* cookie to add in control */
+} SyncOpInfo;
+
diff --git a/ldap/servers/plugins/sync/sync_init.c b/ldap/servers/plugins/sync/sync_init.c
new file mode 100644
index 0000000..d648c79
--- /dev/null
+++ b/ldap/servers/plugins/sync/sync_init.c
@@ -0,0 +1,174 @@
+/** BEGIN COPYRIGHT BLOCK
+ * This Program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; version 2 of the License.
+ *
+ * This Program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception.
+ *
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#include "sync.h"
+
+static Slapi_PluginDesc pdesc = { PLUGIN_NAME, VENDOR, DS_PACKAGE_VERSION, "Context Synchronization (RFC4533) plugin" };
+
+static int sync_start(Slapi_PBlock * pb);
+static int sync_close(Slapi_PBlock * pb);
+static int sync_preop_init( Slapi_PBlock *pb );
+static int sync_postop_init( Slapi_PBlock *pb );
+
+int sync_init( Slapi_PBlock *pb )
+{
+ char *plugin_identity = NULL;
+ int rc = 0;
+
+ slapi_log_error(SLAPI_LOG_TRACE, SYNC_PLUGIN_SUBSYSTEM,
+ "--> sync_init\n");
+
+ /**
+ * Store the plugin identity for later use.
+ * Used for internal operations
+ */
+
+ slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &plugin_identity);
+ PR_ASSERT(plugin_identity);
+
+ if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION,
+ SLAPI_PLUGIN_VERSION_01) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN,
+ (void *) sync_start) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN,
+ (void *) sync_close) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION,
+ (void *) &pdesc) != 0 ) {
+ slapi_log_error(SLAPI_LOG_FATAL, SYNC_PLUGIN_SUBSYSTEM,
+ "sync_init: failed to register plugin\n");
+ rc = 1;
+ }
+
+ if (rc == 0) {
+ char *plugin_type = "preoperation";
+ /* the config change checking post op */
+ if (slapi_register_plugin(
+ plugin_type,
+ 1, /* Enabled */
+ "sync_init", /* this function desc */
+ sync_preop_init,/* init func for post op */
+ SYNC_PREOP_DESC,/* plugin desc */
+ NULL,
+ plugin_identity)) {
+ slapi_log_error(SLAPI_LOG_FATAL, SYNC_PLUGIN_SUBSYSTEM,
+ "sync_init: failed to register preop plugin\n");
+ rc = 1;
+ }
+ }
+
+ if (rc == 0) {
+ char *plugin_type = "postoperation";
+ /* the config change checking post op */
+ if (slapi_register_plugin(plugin_type,
+ 1, /* Enabled */
+ "sync_init", /* this function desc */
+ sync_postop_init, /* init func for post op */
+ SYNC_POSTOP_DESC, /* plugin desc */
+ NULL,
+ plugin_identity )) {
+ slapi_log_error(SLAPI_LOG_FATAL, SYNC_PLUGIN_SUBSYSTEM,
+ "sync_init: failed to register postop plugin\n");
+ rc = 1;
+ }
+ }
+
+ return( rc );
+}
+
+static int
+sync_preop_init( Slapi_PBlock *pb )
+{
+ int rc;
+ rc = slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_SEARCH_FN, (void *) sync_srch_refresh_pre_search);
+ rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_ENTRY_FN, (void *) sync_srch_refresh_pre_entry);
+ rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_RESULT_FN, (void *) sync_srch_refresh_pre_result);
+ rc |= sync_register_operation_extension();
+ return(rc);
+
+}
+
+static int
+sync_postop_init( Slapi_PBlock *pb )
+{
+ int rc;
+ rc = slapi_pblock_set(pb, SLAPI_PLUGIN_POST_ADD_FN, (void *) sync_add_persist_post_op);
+ rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_POST_DELETE_FN, (void *) sync_del_persist_post_op);
+ rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODIFY_FN, (void *) sync_mod_persist_post_op);
+ rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODRDN_FN, (void *) sync_modrdn_persist_post_op);
+ rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_POST_SEARCH_FN, (void *) sync_srch_refresh_post_search);
+ return(rc);
+}
+
+/*
+ sync_start
+ --------------
+ Register the Content Synchronization Control.
+ Initialize locks and queues for the persitent phase.
+*/
+static int
+sync_start(Slapi_PBlock * pb)
+{
+ int argc;
+ char **argv;
+
+ slapi_register_supported_control( LDAP_CONTROL_SYNC,
+ SLAPI_OPERATION_SEARCH );
+ slapi_log_error(SLAPI_LOG_TRACE, SYNC_PLUGIN_SUBSYSTEM,
+ "--> sync_start\n");
+
+ if ( slapi_pblock_get( pb, SLAPI_PLUGIN_ARGC, &argc ) != 0 ||
+ slapi_pblock_get( pb, SLAPI_PLUGIN_ARGV, &argv ) != 0 ) {
+ slapi_log_error( SLAPI_LOG_FATAL, SYNC_PLUGIN_SUBSYSTEM,
+ "unable to get arguments\n" );
+ return( -1 );
+ }
+ sync_persist_initialize(argc, argv);
+
+ return (0);
+}
+
+/*
+ sync_close
+ --------------
+ Free locks and queues allocated.
+*/
+static int
+sync_close(Slapi_PBlock * pb)
+{
+ sync_persist_terminate_all();
+ return (0);
+}
diff --git a/ldap/servers/plugins/sync/sync_persist.c b/ldap/servers/plugins/sync/sync_persist.c
new file mode 100644
index 0000000..d35dde9
--- /dev/null
+++ b/ldap/servers/plugins/sync/sync_persist.c
@@ -0,0 +1,693 @@
+/** BEGIN COPYRIGHT BLOCK
+ent sync_srch_refresh_pre_op(Slapi_PBlock *pb);
+ * This Program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; version 2 of the License.
+ *
+ * This Program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception.
+ *
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#include "sync.h"
+
+/* Main list of established persistent synchronizaton searches */
+static SyncRequestList *sync_request_list = NULL;
+/*
+ * Convenience macros for locking the list of persistent searches
+ */
+#define SYNC_LOCK_READ() slapi_rwlock_rdlock(sync_request_list->sync_req_rwlock)
+#define SYNC_UNLOCK_READ() slapi_rwlock_unlock(sync_request_list->sync_req_rwlock)
+#define SYNC_LOCK_WRITE() slapi_rwlock_wrlock(sync_request_list->sync_req_rwlock)
+#define SYNC_UNLOCK_WRITE() slapi_rwlock_unlock(sync_request_list->sync_req_rwlock)
+
+/*
+ * Convenience macro for checking if the Content Synchronization subsystem has
+ * been initialized.
+ */
+#define SYNC_IS_INITIALIZED() (sync_request_list != NULL)
+
+
+static int sync_add_request( SyncRequest *req );
+static void sync_remove_request( SyncRequest *req );
+static SyncRequest *sync_request_alloc();
+void sync_queue_change( Slapi_Entry *e, Slapi_Entry *eprev, ber_int_t chgtype );
+static void sync_send_results( void *arg );
+static void sync_request_wakeup_all();
+static void sync_node_free( SyncQueueNode **node );
+
+static int sync_acquire_connection (Slapi_Connection *conn);
+static int sync_release_connection (Slapi_PBlock *pb, Slapi_Connection *conn, Slapi_Operation *op, int release);
+
+int sync_add_persist_post_op(Slapi_PBlock *pb)
+{
+ Slapi_Entry *e;
+
+ if ( !SYNC_IS_INITIALIZED()) {
+ return(0);
+ }
+ slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &e);
+ sync_queue_change(e, NULL, LDAP_REQ_ADD);
+ return( 0 );
+}
+
+int sync_del_persist_post_op(Slapi_PBlock *pb)
+{
+ Slapi_Entry *e;
+
+ if ( !SYNC_IS_INITIALIZED()) {
+ return(0);
+ }
+ slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &e);
+ sync_queue_change(e, NULL, LDAP_REQ_DELETE);
+ return( 0 );
+}
+
+int sync_mod_persist_post_op(Slapi_PBlock *pb)
+{
+ Slapi_Entry *e;
+
+ if ( !SYNC_IS_INITIALIZED()) {
+ return(0);
+ }
+ slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &e);
+ sync_queue_change(e, NULL, LDAP_REQ_MODIFY);
+ return( 0 );
+}
+
+int sync_modrdn_persist_post_op(Slapi_PBlock *pb)
+{
+ Slapi_Entry *e, *e_prev;
+
+ if ( !SYNC_IS_INITIALIZED()) {
+ return(0);
+ }
+ slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &e);
+ slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &e_prev);
+ sync_queue_change(e, e_prev, LDAP_REQ_MODRDN);
+ return( 0 );
+}
+
+void
+sync_queue_change( Slapi_Entry *e, Slapi_Entry *eprev, ber_int_t chgtype )
+{
+ SyncRequest *req = NULL;
+ SyncQueueNode *node = NULL;
+ int matched = 0;
+ int prev_match = 0;
+ int cur_match = 0;
+
+ if ( !SYNC_IS_INITIALIZED()) {
+ return;
+ }
+
+ if ( NULL == e ) {
+ /* For now, some backends such as the chaining backend do not provide a post-op entry */
+ return;
+ }
+
+ SYNC_LOCK_READ();
+
+ for ( req = sync_request_list->sync_req_head; NULL != req; req = req->req_next ) {
+ Slapi_DN *base = NULL;
+ int scope;
+ Slapi_Operation *op;
+
+ /* Skip the nodes that have no more active operation
+ */
+ slapi_pblock_get( req->req_pblock, SLAPI_OPERATION, &op );
+ if ( op == NULL || slapi_op_abandoned( req->req_pblock ) ) {
+ continue;
+ }
+
+ slapi_pblock_get( req->req_pblock, SLAPI_SEARCH_TARGET_SDN, &base );
+ slapi_pblock_get( req->req_pblock, SLAPI_SEARCH_SCOPE, &scope );
+ if (NULL == base) {
+ base = slapi_sdn_new_dn_byref(req->req_orig_base);
+ slapi_pblock_set(req->req_pblock, SLAPI_SEARCH_TARGET_SDN, base);
+ }
+
+ /*
+ * See if the entry meets the scope and filter criteria.
+ * We cannot do the acl check here as this thread
+ * would then potentially clash with the ps_send_results()
+ * thread on the aclpb in ps->req_pblock.
+ * By avoiding the acl check in this thread, and leaving all the acl
+ * checking to the ps_send_results() thread we avoid
+ * the req_pblock contention problem.
+ * The lesson here is "Do not give multiple threads arbitary access
+ * to the same pblock" this kind of muti-threaded access
+ * to the same pblock must be done carefully--there is currently no
+ * generic satisfactory way to do this.
+ */
+
+ /* if the change is a modrdn then we need to check if the entry was
+ * moved into scope, out of scope, or stays in scope
+ */
+ if (chgtype == LDAP_REQ_MODRDN)
+ prev_match = slapi_sdn_scope_test( slapi_entry_get_sdn_const(eprev), base, scope ) &&
+ ( 0 == slapi_vattr_filter_test( req->req_pblock, eprev, req->req_filter, 0 /* verify_access */ ));
+
+ cur_match = slapi_sdn_scope_test( slapi_entry_get_sdn_const(e), base, scope ) &&
+ ( 0 == slapi_vattr_filter_test( req->req_pblock, e, req->req_filter, 0 /* verify_access */ ));
+
+ if (prev_match || cur_match) {
+ SyncQueueNode *pOldtail;
+
+ /* The scope and the filter match - enqueue it */
+
+ matched++;
+ node = (SyncQueueNode *)slapi_ch_calloc( 1, sizeof( SyncQueueNode ));
+ node->sync_entry = slapi_entry_dup( e );
+
+ if ( chgtype == LDAP_REQ_MODRDN) {
+ if (prev_match && cur_match)
+ node->sync_chgtype = LDAP_REQ_MODIFY;
+ else if (prev_match)
+ node->sync_chgtype = LDAP_REQ_DELETE;
+ else
+ node->sync_chgtype = LDAP_REQ_ADD;
+ } else {
+ node->sync_chgtype = chgtype;
+ }
+ /* Put it on the end of the list for this sync search */
+ PR_Lock( req->req_lock );
+ pOldtail = req->ps_eq_tail;
+ req->ps_eq_tail = node;
+ if ( NULL == req->ps_eq_head ) {
+ req->ps_eq_head = req->ps_eq_tail;
+ }
+ else {
+ pOldtail->sync_next = req->ps_eq_tail;
+ }
+ PR_Unlock( req->req_lock );
+ }
+ }
+
+ SYNC_UNLOCK_READ();
+
+ /* Were there any matches? */
+ if ( matched ) {
+ /* Notify update threads */
+ sync_request_wakeup_all();
+ slapi_log_error (SLAPI_LOG_TRACE, SYNC_PLUGIN_SUBSYSTEM, "sync search: enqueued entry "
+ "\"%s\" on %d request listeners\n", slapi_entry_get_dn_const(e), matched );
+ } else {
+ slapi_log_error (SLAPI_LOG_TRACE, SYNC_PLUGIN_SUBSYSTEM, "sync search: entry "
+ "\"%s\" not enqueued on any request search listeners\n", slapi_entry_get_dn_const(e) );
+ }
+
+}
+/*
+ * Initialize the list structure which contains the list
+ * of established content sync persistent requests
+ */
+int
+sync_persist_initialize (int argc, char **argv)
+{
+ if ( !SYNC_IS_INITIALIZED()) {
+ sync_request_list = (SyncRequestList *) slapi_ch_calloc( 1, sizeof( SyncRequestList ));
+ if (( sync_request_list->sync_req_rwlock = slapi_new_rwlock()) == NULL ) {
+ slapi_log_error (SLAPI_LOG_FATAL, SYNC_PLUGIN_SUBSYSTEM, "sync_persist_initialize: cannot initialize lock structure(1). ");
+ return( -1 );
+ }
+ if (( sync_request_list->sync_req_cvarlock = PR_NewLock()) == NULL ) {
+ slapi_log_error (SLAPI_LOG_FATAL, SYNC_PLUGIN_SUBSYSTEM, "sync_persist_initialize: cannot initialize lock structure(2). ");
+ return( -1 );
+ }
+ if (( sync_request_list->sync_req_cvar = PR_NewCondVar( sync_request_list->sync_req_cvarlock )) == NULL ) {
+ slapi_log_error (SLAPI_LOG_FATAL, SYNC_PLUGIN_SUBSYSTEM, "sync_persist_initialize: cannot initialize condition variable. ");
+ return( -1 );
+ }
+ sync_request_list->sync_req_head = NULL;
+ sync_request_list->sync_req_cur_persist = 0;
+ sync_request_list->sync_req_max_persist = SYNC_MAX_CONCURRENT;
+ if (argc > 0) {
+ /* for now the only plugin arg is the max concurrent
+ * persistent sync searches
+ */
+ sync_request_list->sync_req_max_persist = sync_number2int(argv[0]);
+ if (sync_request_list->sync_req_max_persist == -1) {
+ sync_request_list->sync_req_max_persist = SYNC_MAX_CONCURRENT;
+ }
+ }
+ }
+ return (0);
+}
+/*
+ * Add the given pblock to the list of established sync searches.
+ * Then, start a thread to send the results to the client as they
+ * are dispatched by add, modify, and modrdn operations.
+ */
+PRThread *
+sync_persist_add (Slapi_PBlock *pb)
+{
+ SyncRequest *req = NULL;
+ char *base;
+ Slapi_Filter *filter;
+
+ if ( SYNC_IS_INITIALIZED() && NULL != pb ) {
+ /* Create the new node */
+ req = sync_request_alloc();
+ req->req_pblock = sync_pblock_copy(pb);
+ slapi_pblock_get(pb, SLAPI_ORIGINAL_TARGET_DN, &base);
+ req->req_orig_base = slapi_ch_strdup(base);
+ slapi_pblock_get( pb, SLAPI_SEARCH_FILTER, &filter );
+ req->req_filter = slapi_filter_dup(filter);
+
+ /* Add it to the head of the list of persistent searches */
+ if ( 0 == sync_add_request( req )) {
+
+ /* Start a thread to send the results */
+ req->req_tid = PR_CreateThread( PR_USER_THREAD, sync_send_results,
+ (void *) req, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE );
+
+ /* Checking if the thread is succesfully created and
+ * if the thread is not created succesfully.... we send
+ * error messages to the Log file
+ */
+ if(NULL == (req->req_tid)){
+ int prerr;
+ prerr = PR_GetError();
+ slapi_log_error(SLAPI_LOG_FATAL, "Content Synchronization Search",
+ "sync_persist_add function: failed to create persitent thread, error %d (%s)\n",
+ prerr, slapi_pr_strerror(prerr));
+ /* Now remove the ps from the list so call the function ps_remove */
+ sync_remove_request(req);
+ PR_DestroyLock ( req->req_lock );
+ req->req_lock = NULL;
+ slapi_ch_free((void **) &req->req_pblock );
+ slapi_ch_free((void **) &req );
+ } else {
+ return( req->req_tid);
+ }
+ }
+ }
+ return( NULL);
+}
+
+int
+sync_persist_startup (PRThread *tid, Sync_Cookie *cookie)
+{
+ SyncRequest *cur;
+ int rc = 1;
+
+ if ( SYNC_IS_INITIALIZED() && NULL != tid ) {
+ SYNC_LOCK_READ();
+ /* Find and change */
+ cur = sync_request_list->sync_req_head;
+ while ( NULL != cur ) {
+ if ( cur->req_tid == tid ) {
+ cur->req_active = PR_TRUE;
+ cur->req_cookie = cookie;
+ rc = 0;
+ break;
+ }
+ cur = cur->req_next;
+ }
+ SYNC_UNLOCK_READ();
+ }
+ return (rc);
+}
+
+
+int
+sync_persist_terminate (PRThread *tid)
+{
+ SyncRequest *cur;
+ int rc = 1;
+
+ if ( SYNC_IS_INITIALIZED() && NULL != tid ) {
+ SYNC_LOCK_READ();
+ /* Find and change */
+ cur = sync_request_list->sync_req_head;
+ while ( NULL != cur ) {
+ if ( cur->req_tid == tid ) {
+ cur->req_active = PR_TRUE;
+ rc = 0;
+ break;
+ }
+ cur = cur->req_next;
+ }
+ SYNC_UNLOCK_READ();
+ }
+ if (rc == 0) {
+ sync_remove_request(cur);
+ }
+ return(rc);
+}
+int
+sync_persist_terminate_all ()
+{
+ SyncRequest *cur;
+
+ if ( SYNC_IS_INITIALIZED() ) {
+ SYNC_LOCK_READ();
+ cur = sync_request_list->sync_req_head;
+ while ( NULL != cur ) {
+ cur->req_complete = PR_TRUE;
+ cur = cur->req_next;
+ }
+ SYNC_UNLOCK_READ();
+ }
+
+ return (0);
+}
+
+/*
+ * Allocate and initialize an empty Sync node.
+ */
+static SyncRequest *
+sync_request_alloc()
+{
+ SyncRequest *req;
+
+ req = (SyncRequest *) slapi_ch_calloc( 1, sizeof( SyncRequest ));
+
+ req->req_pblock = NULL;
+ if (( req->req_lock = PR_NewLock()) == NULL ) {
+ slapi_log_error (SLAPI_LOG_FATAL, SYNC_PLUGIN_SUBSYSTEM, "sync_request_alloc: cannot initialize lock structure. ");
+ slapi_ch_free((void **)&req);
+ return( NULL );
+ }
+ req->req_tid = (PRThread *) NULL;
+ req->req_complete = 0;
+ req->req_cookie = NULL;
+ req->ps_eq_head = req->ps_eq_tail = (SyncQueueNode *) NULL;
+ req->req_next = NULL;
+ req->req_active = PR_FALSE;
+ return req;
+}
+
+
+
+/*
+ * Add the given persistent search to the
+ * head of the list of persistent searches.
+ */
+static int
+sync_add_request( SyncRequest *req )
+{
+ int rc = 0;
+ if ( SYNC_IS_INITIALIZED() && NULL != req ) {
+ SYNC_LOCK_WRITE();
+ if (sync_request_list->sync_req_cur_persist < sync_request_list->sync_req_max_persist) {
+ sync_request_list->sync_req_cur_persist++;
+ req->req_next = sync_request_list->sync_req_head;
+ sync_request_list->sync_req_head = req;
+ } else {
+ rc = 1;
+ }
+ SYNC_UNLOCK_WRITE();
+ }
+ return(rc);
+}
+
+static void
+sync_remove_request( SyncRequest *req )
+{
+ SyncRequest *cur;
+ int removed = 0;
+
+ if ( SYNC_IS_INITIALIZED() && NULL != req ) {
+ SYNC_LOCK_WRITE();
+ if ( NULL == sync_request_list->sync_req_head ) {
+ /* should not happen, attempt to remove a request never added */
+ } else if ( req == sync_request_list->sync_req_head ) {
+ /* Remove from head */
+ sync_request_list->sync_req_head = sync_request_list->sync_req_head->req_next;
+ removed = 1;
+ } else {
+ /* Find and remove from list */
+ cur = sync_request_list->sync_req_head;
+ while ( NULL != cur->req_next ) {
+ if ( cur->req_next == req ) {
+ cur->req_next = cur->req_next->req_next;
+ removed = 1;
+ break;
+ } else {
+ cur = cur->req_next;
+ }
+ }
+ }
+ if (removed) {
+ sync_request_list->sync_req_cur_persist--;
+ }
+ SYNC_UNLOCK_WRITE();
+ if (!removed) {
+ slapi_log_error (SLAPI_LOG_PLUGIN, SYNC_PLUGIN_SUBSYSTEM, "attempt to remove nonexistent req");
+ }
+ }
+}
+
+static void
+sync_request_wakeup_all()
+{
+ if ( SYNC_IS_INITIALIZED()) {
+ PR_Lock( sync_request_list->sync_req_cvarlock );
+ PR_NotifyAllCondVar( sync_request_list->sync_req_cvar );
+ PR_Unlock( sync_request_list->sync_req_cvarlock );
+ }
+}
+static int
+sync_acquire_connection (Slapi_Connection *conn)
+{
+ int rc;
+ /* need to acquire a reference to this connection so that it will not
+ be released or cleaned up out from under us
+
+ in psearch.c it is implemented as:
+ PR_Lock( ps->req_pblock->pb_conn->c_mutex );
+ conn_acq_flag = connection_acquire_nolock(ps->req_pblock->pb_conn);
+ PR_Unlock( ps->req_pblock->pb_conn->c_mutex );
+
+
+ HOW TO DO FROM A PLUGIN
+ - either expose the functions from the connection code in the private api
+ and allow to link them in
+ - or fake a connection structure
+ struct fake_conn {
+ void *needed1
+ void *needed2
+ void *pad1
+ void *pad2
+ void *needed3;
+ }
+ struct fake_conn *c = (struct fake_conn *) conn;
+ c->needed3 ++;
+ this would require knowledge or analysis of the connection structure,
+ could probably be done for servers with a common history
+ */
+ /* use exposed slapi_connection functions */
+ rc = slapi_connection_acquire(conn);
+ return (rc);
+}
+
+static int
+sync_release_connection (Slapi_PBlock *pb, Slapi_Connection *conn, Slapi_Operation *op, int release)
+{
+ /* see comments in sync_acquire_connection */
+
+ /* using exposed connection handling functions */
+
+ slapi_connection_remove_operation(pb, conn, op, release);
+
+ return(0);
+}
+/*
+ * Thread routine for sending search results to a client
+ * which is persistently waiting for them.
+ *
+ * This routine will terminate when either (a) the ps_complete
+ * flag is set, or (b) the associated operation is abandoned.
+ * In any case, the thread won't notice until it wakes from
+ * sleeping on the ps_list condition variable, so it needs
+ * to be awakened.
+ */
+static void
+sync_send_results( void *arg )
+{
+ SyncRequest *req = (SyncRequest *)arg;
+ SyncQueueNode *qnode, *qnodenext;
+ int conn_acq_flag = 0;
+ Slapi_Connection *conn = NULL;
+ Slapi_Operation *op = NULL;
+ int rc;
+ PRUint64 connid;
+ int opid;
+
+ slapi_pblock_get(req->req_pblock, SLAPI_CONN_ID, &connid);
+ slapi_pblock_get(req->req_pblock, SLAPI_OPERATION_ID, &opid);
+ slapi_pblock_get(req->req_pblock, SLAPI_CONNECTION, &conn);
+ slapi_pblock_get(req->req_pblock, SLAPI_OPERATION, &op);
+
+ conn_acq_flag = sync_acquire_connection (conn);
+ if (conn_acq_flag) {
+ slapi_log_error(SLAPI_LOG_FATAL, "Content Synchronization Search",
+ "conn=%" NSPRIu64 " op=%d Could not acquire the connection - aborted\n",
+ (long long unsigned int)connid, opid);
+ }
+
+ PR_Lock( sync_request_list->sync_req_cvarlock );
+
+ while ( (conn_acq_flag == 0) && !req->req_complete ) {
+ /* Check for an abandoned operation */
+ Slapi_Operation *op;
+ slapi_pblock_get(req->req_pblock, SLAPI_OPERATION, &op);
+ if ( op == NULL || slapi_op_abandoned( req->req_pblock ) ) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, "Content Synchronization Search",
+ "conn=%" NSPRIu64 " op=%d Operation no longer active - terminating\n",
+ (long long unsigned int)connid, opid);
+ break;
+ }
+ if ( NULL == req->ps_eq_head || !req->req_active) {
+ /* Nothing to do yet, or the refresh phase is not yet completed */
+ /* If an operation is abandoned, we do not get notified by the
+ * connection code. Wake up every second to check if thread
+ * should terminate.
+ */
+ PR_WaitCondVar( sync_request_list->sync_req_cvar, PR_SecondsToInterval(1) );
+ } else {
+ /* dequeue the item */
+ int attrsonly;
+ char **attrs;
+ char **noattrs = NULL;
+ LDAPControl **ectrls = NULL;
+ Slapi_Entry *ec;
+ int chg_type;
+
+ /* deque one element */
+ PR_Lock( req->req_lock );
+ qnode = req->ps_eq_head;
+ req->ps_eq_head = qnode->sync_next;
+ if ( NULL == req->ps_eq_head ) {
+ req->ps_eq_tail = NULL;
+ }
+ PR_Unlock( req->req_lock );
+
+ /* Get all the information we need to send the result */
+ ec = qnode->sync_entry;
+ slapi_pblock_get( req->req_pblock, SLAPI_SEARCH_ATTRS, &attrs );
+ slapi_pblock_get( req->req_pblock, SLAPI_SEARCH_ATTRSONLY, &attrsonly );
+
+ /*
+ * Send the result. Since send_ldap_search_entry can block for
+ * up to 30 minutes, we relinquish all locks before calling it.
+ */
+ PR_Unlock(sync_request_list->sync_req_cvarlock);
+
+ /*
+ * The entry is in the right scope and matches the filter
+ * but we need to redo the filter test here to check access
+ * controls. See the comments at the slapi_filter_test()
+ * call in sync_persist_add().
+ */
+
+ if ( slapi_vattr_filter_test( req->req_pblock, ec, req->req_filter,
+ 1 /* verify_access */ ) == 0 ) {
+ slapi_pblock_set( req->req_pblock, SLAPI_SEARCH_RESULT_ENTRY, ec );
+
+ /* NEED TO BUILD THE CONTROL */
+ switch (qnode->sync_chgtype){
+ case LDAP_REQ_ADD:
+ chg_type = LDAP_SYNC_ADD;
+ break;
+ case LDAP_REQ_MODIFY:
+ chg_type = LDAP_SYNC_MODIFY;
+ break;
+ case LDAP_REQ_MODRDN:
+ chg_type = LDAP_SYNC_MODIFY;
+ break;
+ case LDAP_REQ_DELETE:
+ chg_type = LDAP_SYNC_DELETE;
+ noattrs = (char **)slapi_ch_calloc(2, sizeof (char *));
+ noattrs[0] = slapi_ch_strdup("1.1");
+ noattrs[1] = NULL;
+ break;
+ }
+ ectrls = (LDAPControl **)slapi_ch_calloc(2, sizeof (LDAPControl *));
+ if (req->req_cookie)
+ sync_cookie_update(req->req_cookie, ec);
+ sync_create_state_control(ec, &ectrls[0], chg_type, req->req_cookie);
+ rc = slapi_send_ldap_search_entry( req->req_pblock,
+ ec, ectrls,
+ noattrs?noattrs:attrs, attrsonly );
+ if (rc) {
+ slapi_log_error(SLAPI_LOG_CONNS, SYNC_PLUGIN_SUBSYSTEM,
+ "Error %d sending entry %s\n",
+ rc, slapi_entry_get_dn_const(ec));
+ }
+ ldap_controls_free(ectrls);
+ slapi_ch_array_free(noattrs);
+
+ }
+ PR_Lock(sync_request_list->sync_req_cvarlock);
+
+ /* Deallocate our wrapper for this entry */
+ sync_node_free( &qnode );
+ }
+ }
+ PR_Unlock( sync_request_list->sync_req_cvarlock );
+ sync_remove_request( req );
+
+ /* indicate the end of search */
+
+ sync_release_connection(req->req_pblock, conn, op, conn_acq_flag == 0);
+
+ PR_DestroyLock ( req->req_lock );
+ req->req_lock = NULL;
+
+ slapi_ch_free((void **) &req->req_pblock );
+ slapi_ch_free((void **) &req->req_orig_base );
+ slapi_filter_free(req->req_filter, 1);
+ sync_cookie_free(&req->req_cookie);
+ for ( qnode = req->ps_eq_head; qnode; qnode = qnodenext) {
+ qnodenext = qnode->sync_next;
+ sync_node_free( &qnode );
+ }
+ slapi_ch_free((void **) &req );
+}
+
+
+/*
+ * Free a sync update node (and everything it holds).
+ */
+static void
+sync_node_free( SyncQueueNode **node )
+{
+ if ( node != NULL && *node != NULL ) {
+ if ( (*node)->sync_entry != NULL ) {
+ slapi_entry_free( (*node)->sync_entry );
+ (*node)->sync_entry = NULL;
+ }
+ slapi_ch_free( (void **)node );
+ }
+}
diff --git a/ldap/servers/plugins/sync/sync_refresh.c b/ldap/servers/plugins/sync/sync_refresh.c
new file mode 100644
index 0000000..1487289
--- /dev/null
+++ b/ldap/servers/plugins/sync/sync_refresh.c
@@ -0,0 +1,732 @@
+/** BEGIN COPYRIGHT BLOCK
+ * This Program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; version 2 of the License.
+ *
+ * This Program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception.
+ *
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#include "sync.h"
+
+static SyncOpInfo *new_SyncOpInfo(int flag, Sync_Cookie *cookie);
+
+static int sync_extension_type;
+static int sync_extension_handle;
+
+static SyncOpInfo *sync_get_operation_extension(Slapi_PBlock *pb);
+static void sync_set_operation_extension(Slapi_PBlock *pb, SyncOpInfo *spec);
+static int sync_find_ref_by_uuid(Sync_UpdateNode *updates, int stop, char *uniqueid);
+static void sync_free_update_nodes (Sync_UpdateNode **updates, int count);
+Slapi_Entry *sync_deleted_entry_from_changelog(Slapi_Entry *cl_entry);
+static int sync_feature_allowed (Slapi_PBlock *pb);
+
+static int sync_feature_allowed (Slapi_PBlock *pb)
+{
+ int isroot = 0;
+ int ldapcode = LDAP_SUCCESS;
+
+ slapi_pblock_get(pb, SLAPI_REQUESTOR_ISROOT, &isroot);
+ if ( !isroot) {
+ char *dn;
+ Slapi_Entry *feature = NULL;
+
+ /* Fetch the feature entry and see if the requestor is allowed access. */
+ dn = slapi_ch_smprintf("dn: oid=%s,cn=features,cn=config", LDAP_CONTROL_SYNC);
+ if ((feature = slapi_str2entry(dn,0)) != NULL) {
+ char *dummy_attr = "1.1";
+
+ ldapcode = slapi_access_allowed(pb, feature, dummy_attr, NULL, SLAPI_ACL_READ);
+ }
+
+ /* If the feature entry does not exist, deny use of the control. Only
+ * the root DN will be allowed to use the control in this case. */
+ if ((feature == NULL) || (ldapcode != LDAP_SUCCESS)) {
+ ldapcode = LDAP_INSUFFICIENT_ACCESS;
+ }
+ slapi_ch_free((void **)&dn);
+ slapi_entry_free(feature);
+ }
+ return(ldapcode);
+}
+
+int sync_srch_refresh_pre_search(Slapi_PBlock *pb)
+{
+
+ LDAPControl **requestcontrols;
+ struct berval *psbvp;
+ Sync_Cookie *client_cookie = NULL;
+ Sync_Cookie *session_cookie = NULL;
+ int rc = 0;
+ int sync_persist = 0;
+ PRThread *tid = NULL;
+ int entries_sent = 0;
+
+ slapi_pblock_get (pb, SLAPI_REQCONTROLS, &requestcontrols);
+ if ( slapi_control_present( requestcontrols, LDAP_CONTROL_SYNC, &psbvp, NULL )){
+ char *cookie = NULL;
+ int mode = 1;
+ int refresh = 0;
+
+ if ( sync_parse_control_value( psbvp, &mode,
+ &refresh, &cookie ) != LDAP_SUCCESS )
+ {
+ rc = 1;
+ goto error_return;
+ } else {
+ /* control is valid, check if usere is allowed to perform sync searches */
+ rc = sync_feature_allowed(pb);
+ if (rc) {
+ sync_result_err(pb,rc,NULL);
+ goto error_return;
+ }
+ }
+
+ if ( mode == 1 || mode == 3 )
+ {
+
+ /* we need to return a cookie in the result message
+ * indicating a state to be used in future sessions
+ * as starting point - create it now
+ */
+ session_cookie = sync_cookie_create(pb);
+ /*
+ * if mode is persist we need to setup the persit handler
+ * to catch the mods while the refresh is done
+ */
+ if ( mode == 3 )
+ {
+ tid = sync_persist_add(pb);
+ if ( tid )
+ sync_persist = 1;
+ else {
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ sync_result_err(pb,rc,"Too many active synchronization sessions");
+ goto error_return;
+ }
+ }
+ /*
+ * now handl the refresh request
+ * there are two scenarios
+ * 1. no cookie is provided this means send all entries matching the search request
+ * 2. a cookie is provided: send all entries changed since the cookie was issued
+ * -- return an error if the cookie is invalid
+ * -- return e-syncRefreshRequired if the data referenced in the cookie are no
+ * longer in the history
+ */
+ if (cookie &&
+ ( client_cookie = sync_cookie_parse (cookie))) {
+ if (sync_cookie_isvalid(client_cookie, session_cookie)) {
+ rc = sync_refresh_update_content(pb, client_cookie, session_cookie);
+ if (rc == 0)
+ entries_sent = 1;
+ if (sync_persist)
+ rc = sync_intermediate_msg(pb, LDAP_TAG_SYNC_REFRESH_DELETE, session_cookie, NULL);
+ else
+ rc = sync_result_msg(pb, session_cookie);
+ } else {
+ rc = E_SYNC_REFRESH_REQUIRED;
+ sync_result_err(pb,rc, "Invalid session cookie");
+ }
+ } else {
+ rc = sync_refresh_initial_content (pb, sync_persist, session_cookie);
+ if (rc == 0 && !sync_persist)
+ /* maintained in postop code */
+ session_cookie = NULL;
+ /* if persis it will be handed over to persist code */
+ }
+
+ if ( rc ) {
+ if (sync_persist)
+ sync_persist_terminate (tid);
+ goto error_return;
+ } else if (sync_persist){
+ Slapi_Operation *operation;
+
+ slapi_pblock_get(pb, SLAPI_OPERATION, &operation);
+ rc = sync_persist_startup(tid, session_cookie);
+
+ if (rc == 0) {
+ session_cookie = NULL; /* maintained in persist code */
+ slapi_operation_set_flag(operation, OP_FLAG_SYNC_PERSIST);
+ }
+ }
+
+
+ } else {
+ /* unknown mode, return an error */
+ rc = 1;
+ }
+error_return:
+ sync_cookie_free(&client_cookie);
+ sync_cookie_free(&session_cookie);
+ slapi_ch_free((void **)&cookie);
+ }
+
+ /* if we sent the entries
+ * return "error" to abort normal search
+ */
+ if ( entries_sent > 0 ) {
+ return(1);
+ } else {
+ return(rc);
+ }
+}
+
+int sync_srch_refresh_post_search(Slapi_PBlock *pb)
+{
+ int rc = 0;
+ SyncOpInfo *info = sync_get_operation_extension(pb);
+
+ if (!info) {
+ return (0); /* nothing to do */
+ }
+ if (info->send_flag & SYNC_FLAG_SEND_INTERMEDIATE) {
+ rc = sync_intermediate_msg(pb, LDAP_TAG_SYNC_REFRESH_DELETE, info->cookie, NULL);
+ /* the refresh phase is over, now the post op
+ * plugins will create the state control
+ * depending on the operation type, reset flag
+ */
+ info->send_flag &= ~SYNC_FLAG_ADD_STATE_CTRL;
+ }
+ if (info->send_flag & SYNC_FLAG_ADD_DONE_CTRL) {
+ LDAPControl **ctrl = (LDAPControl **)slapi_ch_calloc(2, sizeof (LDAPControl *));
+ char *cookiestr = sync_cookie2str(info->cookie);
+ sync_create_sync_done_control( &ctrl[0], 0, cookiestr);
+ slapi_pblock_set(pb, SLAPI_RESCONTROLS, ctrl);
+ slapi_ch_free((void **)&cookiestr);
+ }
+ return(rc);
+}
+
+int sync_srch_refresh_pre_entry(Slapi_PBlock *pb)
+{
+ int rc = 0;
+ SyncOpInfo *info = sync_get_operation_extension(pb);
+
+ if (!info) {
+ rc = 0; /* nothing to do */
+ } else if (info->send_flag & SYNC_FLAG_ADD_STATE_CTRL) {
+ Slapi_Entry *e;
+ slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_ENTRY, &e);
+ LDAPControl **ctrl = (LDAPControl **)slapi_ch_calloc(2, sizeof (LDAPControl *));
+ sync_create_state_control(e, &ctrl[0], LDAP_SYNC_ADD, NULL);
+ slapi_pblock_set(pb, SLAPI_SEARCH_CTRLS, ctrl);
+ }
+ return(rc);
+}
+
+int sync_srch_refresh_pre_result(Slapi_PBlock *pb)
+{
+ SyncOpInfo *info = sync_get_operation_extension(pb);
+
+ if (!info) {
+ return 0; /* nothing to do */
+ }
+ if (info->send_flag & SYNC_FLAG_NO_RESULT ) {
+ return(1);
+ } else {
+ return(0);
+ }
+}
+
+static void
+sync_free_update_nodes (Sync_UpdateNode **updates, int count)
+{
+ int i;
+
+ for (i=0; i<count;i++) {
+ if ((*updates)[i].upd_uuid)
+ slapi_ch_free((void **)&((*updates)[i].upd_uuid));
+ if ((*updates)[i].upd_e)
+ slapi_entry_free((*updates)[i].upd_e);
+ }
+ slapi_ch_free((void **)updates);
+}
+
+int
+sync_refresh_update_content(Slapi_PBlock *pb, Sync_Cookie *client_cookie, Sync_Cookie *server_cookie)
+{
+ Slapi_PBlock *seq_pb;
+ char *filter;
+ Sync_CallBackData cb_data;
+ int rc;
+ int chg_count = server_cookie->cookie_change_info -
+ client_cookie->cookie_change_info + 1;
+
+ cb_data.cb_updates = (Sync_UpdateNode *)slapi_ch_calloc(chg_count, sizeof(Sync_UpdateNode));
+
+ seq_pb = slapi_pblock_new();
+ slapi_pblock_init(seq_pb);
+
+ cb_data.orig_pb = pb;
+ cb_data.change_start = client_cookie->cookie_change_info;
+
+ filter = slapi_ch_smprintf("(&(changenumber>=%d)(changenumber<=%d))",
+ client_cookie->cookie_change_info,
+ server_cookie->cookie_change_info);
+ slapi_search_internal_set_pb(
+ seq_pb,
+ CL_SRCH_BASE,
+ LDAP_SCOPE_ONE,
+ filter,
+ NULL,
+ 0,
+ NULL, NULL,
+ plugin_get_default_component_id(),
+ 0);
+
+ rc = slapi_search_internal_callback_pb (
+ seq_pb, &cb_data, NULL, sync_read_entry_from_changelog, NULL);
+ slapi_pblock_destroy(seq_pb);
+
+ /* Now send the deleted entries in a sync info message
+ * and the modified entries as single entries
+ */
+ sync_send_deleted_entries(pb, cb_data.cb_updates, chg_count, server_cookie);
+ sync_send_modified_entries(pb, cb_data.cb_updates, chg_count);
+
+ sync_free_update_nodes(&cb_data.cb_updates, chg_count);
+ slapi_ch_free((void **)&filter);
+ return (rc);
+}
+
+int
+sync_refresh_initial_content(Slapi_PBlock *pb, int sync_persist, Sync_Cookie *sc)
+{
+ /* the entries will be sent in the normal search process, but
+ * - a control has to be sent with each entry
+ * if sync persist:
+ * - an intermediate response has to be sent
+ * - no result message must be sent
+ *
+ * else
+ * - a result message with a sync done control has to be sent
+ *
+ * setup on operation extension to take care of in
+ * pre_entry, pre_result and post_search plugins
+ */
+ SyncOpInfo *info;
+
+ if (sync_persist) {
+ info = new_SyncOpInfo
+ (SYNC_FLAG_ADD_STATE_CTRL |
+ SYNC_FLAG_SEND_INTERMEDIATE |
+ SYNC_FLAG_NO_RESULT,
+ sc);
+ } else {
+ info = new_SyncOpInfo
+ (SYNC_FLAG_ADD_STATE_CTRL |
+ SYNC_FLAG_ADD_DONE_CTRL,
+ sc);
+ }
+ sync_set_operation_extension(pb, info);
+
+ return(0);
+}
+
+static int
+sync_str2chgreq(char *chgtype)
+{
+ if (chgtype == NULL) {
+ return(-1);
+ }
+ if (strcasecmp(chgtype,"add") == 0) {
+ return(LDAP_REQ_ADD);
+ } else if (strcasecmp(chgtype,"modify") == 0) {
+ return(LDAP_REQ_MODIFY);
+ } else if (strcasecmp(chgtype,"modrdn") == 0) {
+ return(LDAP_REQ_MODRDN);
+ } else if (strcasecmp(chgtype,"delete") == 0) {
+ return(LDAP_REQ_DELETE);
+ } else {
+ return(-1);
+ }
+}
+
+static char*
+sync_get_attr_value_from_entry( Slapi_Entry *cl_entry, char *attrtype)
+{
+ Slapi_Value *sval=NULL;
+ const struct berval *value;
+ char *strvalue = NULL;
+ if ( NULL != cl_entry ) {
+ Slapi_Attr *chattr = NULL;
+ sval = NULL;
+ value = NULL;
+ if ( slapi_entry_attr_find( cl_entry, attrtype, &chattr ) == 0 ) {
+ slapi_attr_first_value( chattr,&sval );
+ if ( NULL != sval ) {
+ value = slapi_value_get_berval ( sval );
+ if( NULL != value && NULL != value->bv_val &&
+ '\0' != value->bv_val[0]) {
+ strvalue = slapi_ch_strdup( value->bv_val);
+ }
+ }
+ }
+ }
+ return (strvalue);
+}
+
+static int
+sync_find_ref_by_uuid(Sync_UpdateNode *updates, int stop, char *uniqueid)
+{
+ int rc = -1;
+ int i;
+ for (i=0; i<stop; i++) {
+ if ( updates[i].upd_uuid && (0 == strcmp(uniqueid, updates[i].upd_uuid))) {
+ rc = i;
+ break;
+ }
+ }
+ return (rc);
+}
+
+static int
+sync_is_entry_in_scope(Slapi_PBlock *pb, Slapi_Entry *db_entry)
+{
+ Slapi_Filter *origfilter;
+ slapi_pblock_get( pb, SLAPI_SEARCH_FILTER, &origfilter );
+ if (db_entry &&
+ sync_is_active(db_entry, pb) &&
+ (slapi_vattr_filter_test( pb, db_entry, origfilter, 1) == 0)) {
+ return(1);
+ } else {
+ return(0);
+ }
+}
+
+Slapi_Entry *
+sync_deleted_entry_from_changelog(Slapi_Entry *cl_entry)
+{
+ Slapi_Entry *db_entry = NULL;
+ char *entrydn = NULL;
+ char *uniqueid = NULL;
+
+ entrydn = sync_get_attr_value_from_entry (cl_entry, CL_ATTR_ENTRYDN);
+ uniqueid = sync_get_attr_value_from_entry (cl_entry, CL_ATTR_UNIQUEID);
+
+ /* when the Retro CL can provide the deleted entry
+ * the entry will be taken from th RCL.
+ * For now. just create an entry to holde the nsuniqueid
+ */
+ db_entry = slapi_entry_alloc();
+ slapi_entry_init(db_entry, entrydn, NULL);
+ slapi_entry_add_string(db_entry, "nsuniqueid", uniqueid);
+ slapi_ch_free((void**)&uniqueid);
+
+ return(db_entry);
+}
+
+int
+sync_read_entry_from_changelog( Slapi_Entry *cl_entry, void *cb_data)
+{
+ char *uniqueid = NULL;
+ char *chgtype = NULL;
+ char *chgnr = NULL;
+ int chg_req;
+ int prev = 0;
+ int index = 0;
+ Sync_CallBackData *cb = (Sync_CallBackData *) cb_data;
+
+ uniqueid = sync_get_attr_value_from_entry (cl_entry, CL_ATTR_UNIQUEID);
+ chgtype = sync_get_attr_value_from_entry (cl_entry, CL_ATTR_CHGTYPE);
+ chgnr = sync_get_attr_value_from_entry (cl_entry, CL_ATTR_CHANGENUMBER);
+
+ if (uniqueid == NULL) {
+ slapi_log_error (SLAPI_LOG_FATAL, SYNC_PLUGIN_SUBSYSTEM,
+ "Retro Changelog does not provied nsuniquedid."
+ "Check RCL plugin configuration." );
+ }
+
+
+ index = sync_number2int(chgnr) - cb->change_start;
+ chg_req = sync_str2chgreq(chgtype);
+ switch (chg_req){
+ case LDAP_REQ_ADD:
+ /* nsuniqueid cannot exist, just add reference */
+ cb->cb_updates[index].upd_chgtype = LDAP_REQ_ADD;
+ cb->cb_updates[index].upd_uuid = uniqueid;
+ break;
+ case LDAP_REQ_MODIFY:
+ /* check if we have seen this uuid already */
+ prev = sync_find_ref_by_uuid(cb->cb_updates, index, uniqueid);
+ if (prev == -1) {
+ cb->cb_updates[index].upd_chgtype = LDAP_REQ_MODIFY;
+ cb->cb_updates[index].upd_uuid = uniqueid;
+ } else {
+ /* was add or mod, keep it */
+ cb->cb_updates[index].upd_uuid = 0;
+ cb->cb_updates[index].upd_chgtype = 0;
+ slapi_ch_free((void **)&uniqueid);
+ }
+ break;
+ case LDAP_REQ_MODRDN:
+ {
+ /* if it is a modrdn, we finally need to decide if this will
+ * trigger a present or delete state, keep the info that
+ * the entry was subject to a modrdn
+ */
+ int new_scope = 0;
+ int old_scope = 0;
+ Slapi_DN *original_dn;
+ char *newsuperior = sync_get_attr_value_from_entry (cl_entry, CL_ATTR_NEWSUPERIOR);
+ char *entrydn = sync_get_attr_value_from_entry (cl_entry, CL_ATTR_ENTRYDN);
+ /* if newsuperior is set we need to checkif the entry has been moved into
+ * or moved out of the scope of the synchronization request
+ */
+ original_dn = slapi_sdn_new_dn_byref(entrydn);
+ old_scope = sync_is_active_scope(original_dn,cb->orig_pb);
+ slapi_sdn_free(&original_dn);
+ slapi_ch_free((void **)&entrydn);
+ if (newsuperior) {
+ Slapi_DN *newbase;
+ newbase = slapi_sdn_new_dn_byref(newsuperior);
+ new_scope = sync_is_active_scope(newbase, cb->orig_pb);
+ slapi_ch_free((void **)&newsuperior);
+ slapi_sdn_free(&newbase);
+ } else {
+ /* scope didn't change */
+ new_scope = old_scope;
+ }
+ prev = sync_find_ref_by_uuid(cb->cb_updates, index, uniqueid);
+ if ( old_scope && new_scope ) {
+ /* nothing changed, it's just a MOD */
+ if (prev == -1) {
+ cb->cb_updates[index].upd_chgtype = LDAP_REQ_MODIFY;
+ cb->cb_updates[index].upd_uuid = uniqueid;
+ } else {
+ cb->cb_updates[index].upd_uuid = 0;
+ cb->cb_updates[index].upd_chgtype = 0;
+ slapi_ch_free((void **)&uniqueid);
+ }
+ } else if ( old_scope ) {
+ /* it was moved out of scope, handle as DEL */
+ if (prev == -1) {
+ cb->cb_updates[index].upd_chgtype = LDAP_REQ_DELETE;
+ cb->cb_updates[index].upd_uuid = uniqueid;
+ cb->cb_updates[index].upd_e = sync_deleted_entry_from_changelog(cl_entry);
+ } else {
+ cb->cb_updates[prev].upd_chgtype = LDAP_REQ_DELETE;
+ cb->cb_updates[prev].upd_e = sync_deleted_entry_from_changelog(cl_entry);
+ slapi_ch_free((void **)&uniqueid);
+ }
+ } else if ( new_scope ) {
+ /* moved into scope, handle as ADD */
+ cb->cb_updates[index].upd_chgtype = LDAP_REQ_ADD;
+ cb->cb_updates[index].upd_uuid = uniqueid;
+ } else {
+ /* nothing to do */
+ }
+ slapi_sdn_free(&original_dn);
+ break;
+ }
+ case LDAP_REQ_DELETE:
+ /* check if we have seen this uuid already */
+ prev = sync_find_ref_by_uuid(cb->cb_updates, index, uniqueid);
+ if (prev == -1) {
+ cb->cb_updates[index].upd_chgtype = LDAP_REQ_DELETE;
+ cb->cb_updates[index].upd_uuid = uniqueid;
+ cb->cb_updates[index].upd_e = sync_deleted_entry_from_changelog(cl_entry);
+ } else {
+ /* if it was added since last cookie state, we
+ * can ignoere it */
+ if (cb->cb_updates[prev].upd_chgtype == LDAP_REQ_ADD) {
+ slapi_ch_free((void **)&(cb->cb_updates[prev].upd_uuid));
+ slapi_ch_free((void **)&uniqueid);
+ cb->cb_updates[prev].upd_uuid = NULL;
+ cb->cb_updates[index].upd_uuid = NULL;
+ } else {
+ /* ignore previous mod */
+ cb->cb_updates[index].upd_uuid = NULL;
+ cb->cb_updates[prev].upd_chgtype = LDAP_REQ_DELETE;
+ cb->cb_updates[prev].upd_e = sync_deleted_entry_from_changelog(cl_entry);
+ }
+ }
+ break;
+ }
+ slapi_ch_free((void **)&chgtype);
+ slapi_ch_free((void **)&chgnr);
+
+ return (0);
+}
+#define SYNC_MAX_DELETED_UUID_BATCH 50
+
+void
+sync_send_deleted_entries(Slapi_PBlock *pb, Sync_UpdateNode *upd, int chg_count, Sync_Cookie *cookie)
+{
+ char *syncUUIDs[SYNC_MAX_DELETED_UUID_BATCH + 1];
+ int uuid_index = 0;
+ int index, i;
+
+ syncUUIDs[0] = NULL;
+ for (index=0; index < chg_count; index++) {
+ if (upd[index].upd_chgtype == LDAP_REQ_DELETE &&
+ upd[index].upd_uuid ) {
+ if (uuid_index < SYNC_MAX_DELETED_UUID_BATCH) {
+ syncUUIDs[uuid_index++] = sync_nsuniqueid2uuid(upd[index].upd_uuid);
+ } else {
+ /* max number of uuids to be sent in one sync info message */
+ syncUUIDs[uuid_index] = NULL;
+ sync_intermediate_msg (pb, LDAP_TAG_SYNC_ID_SET, cookie, &syncUUIDs[0]);
+ for (i=0; i<uuid_index;i++) {
+ slapi_ch_free((void **)&syncUUIDs[i]);
+ syncUUIDs[i] = NULL;
+ }
+ uuid_index = 0;
+ }
+ }
+ }
+
+ if (uuid_index > 0 && syncUUIDs[uuid_index-1]) {
+ /* more entries to send */
+ syncUUIDs[uuid_index] = NULL;
+ sync_intermediate_msg (pb, LDAP_TAG_SYNC_ID_SET, cookie, &syncUUIDs[0]);
+ for (i=0; i<uuid_index;i++) {
+ slapi_ch_free((void **)&syncUUIDs[i]);
+ syncUUIDs[i] = NULL;
+ }
+ }
+}
+
+void
+sync_send_modified_entries(Slapi_PBlock *pb, Sync_UpdateNode *upd, int chg_count)
+{
+ int index;
+
+ for (index=0; index < chg_count; index++) {
+ if (upd[index].upd_chgtype != LDAP_REQ_DELETE &&
+ upd[index].upd_uuid )
+
+ sync_send_entry_from_changelog(pb, upd[index].upd_chgtype, upd[index].upd_uuid);
+ }
+}
+
+int
+sync_send_entry_from_changelog(Slapi_PBlock *pb,int chg_req, char *uniqueid)
+{
+ Slapi_Entry *db_entry = NULL;
+ int chg_type = LDAP_SYNC_ADD;
+ int rv;
+ Slapi_PBlock *search_pb = NULL;
+ Slapi_Entry **entries = NULL;
+ char *origbase;
+ char *filter = slapi_ch_smprintf("(nsuniqueid=%s)",uniqueid);
+
+ slapi_pblock_get( pb, SLAPI_ORIGINAL_TARGET_DN, &origbase );
+ search_pb = slapi_pblock_new();
+ slapi_search_internal_set_pb(search_pb, origbase,
+ LDAP_SCOPE_SUBTREE, filter,
+ NULL, 0, NULL, NULL, plugin_get_default_component_id(), 0);
+ slapi_search_internal_pb(search_pb);
+ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &rv);
+ if ( rv == LDAP_SUCCESS) {
+ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
+ if (entries)
+ db_entry = *entries; /* there can only be one */
+ }
+
+ if (db_entry && sync_is_entry_in_scope(pb, db_entry)) {
+ LDAPControl **ctrl = (LDAPControl **)slapi_ch_calloc(2, sizeof (LDAPControl *));
+ sync_create_state_control(db_entry, &ctrl[0], chg_type, NULL);
+ slapi_send_ldap_search_entry (pb, db_entry, ctrl, NULL, 0);
+ ldap_controls_free(ctrl);
+ }
+ slapi_free_search_results_internal(search_pb);
+ slapi_pblock_destroy(search_pb);
+ slapi_ch_free((void **)&filter);
+ return (0);
+}
+
+static SyncOpInfo*
+new_SyncOpInfo(int flag, Sync_Cookie *cookie) {
+ SyncOpInfo *spec = (SyncOpInfo *)slapi_ch_calloc(1, sizeof(SyncOpInfo));
+ spec->send_flag = flag;
+ spec->cookie = cookie;
+
+ return spec;
+}
+/* consumer operation extension constructor */
+static void *
+sync_operation_extension_ctor(void *object, void *parent)
+{
+ /* we only set the extension value explicitly if the
+ client requested the control - see deref_pre_search */
+ return NULL; /* we don't set anything in the ctor */
+}
+
+/* consumer operation extension destructor */
+static void
+sync_delete_SyncOpInfo(SyncOpInfo **info)
+{
+ if (info && *info) {
+ sync_cookie_free(&((*info)->cookie));
+ slapi_ch_free((void **)info);
+ }
+}
+
+static void
+sync_operation_extension_dtor(void *ext, void *object, void *parent)
+{
+ SyncOpInfo *spec = (SyncOpInfo *)ext;
+ sync_delete_SyncOpInfo(&spec);
+}
+
+static SyncOpInfo *
+sync_get_operation_extension(Slapi_PBlock *pb)
+{
+ Slapi_Operation *op;
+
+ slapi_pblock_get(pb, SLAPI_OPERATION, &op);
+ return (SyncOpInfo *)slapi_get_object_extension(sync_extension_type,
+ op, sync_extension_handle);
+}
+
+static void
+sync_set_operation_extension(Slapi_PBlock *pb, SyncOpInfo *spec)
+{
+ Slapi_Operation *op;
+
+ slapi_pblock_get(pb, SLAPI_OPERATION, &op);
+ slapi_set_object_extension(sync_extension_type, op,
+ sync_extension_handle, (void *)spec);
+}
+
+int
+sync_register_operation_extension(void)
+{
+ return slapi_register_object_extension(SYNC_PLUGIN_SUBSYSTEM,
+ SLAPI_EXT_OPERATION,
+ sync_operation_extension_ctor,
+ sync_operation_extension_dtor,
+ &sync_extension_type,
+ &sync_extension_handle);
+}
diff --git a/ldap/servers/plugins/sync/sync_util.c b/ldap/servers/plugins/sync/sync_util.c
new file mode 100644
index 0000000..9e98561
--- /dev/null
+++ b/ldap/servers/plugins/sync/sync_util.c
@@ -0,0 +1,685 @@
+/** BEGIN COPYRIGHT BLOCK
+ * This Program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; version 2 of the License.
+ *
+ * This Program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception.
+ *
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#include "sync.h"
+
+static struct berval * create_syncinfo_value( int type, const char *cookie, const char **uuids);
+static char * sync_cookie_get_server_info(Slapi_PBlock *pb);
+static char * sync_cookie_get_client_info(Slapi_PBlock *pb);
+
+/*
+ * Parse the value from an LDAPv3 sync request control. They look
+ * like this:
+ *
+ * syncRequestValue ::= SEQUENCE {
+ * mode ENUMERATED {
+ * -- 0 unused
+ * refreshOnly (1),
+ * -- 2 reserved
+ * refreshAndPersist (3)
+ * },
+ * cookie syncCookie OPTIONAL,
+ * reloadHint BOOLEAN DEFAULT FALSE
+ * }
+ *
+ * Return an LDAP error code (LDAP_SUCCESS if all goes well).
+ *
+ */
+int
+sync_parse_control_value( struct berval *psbvp, ber_int_t *mode, int *reload, char **cookie )
+{
+ int rc= LDAP_SUCCESS;
+
+ if ( psbvp->bv_len == 0 || psbvp->bv_val == NULL )
+ {
+ rc= LDAP_PROTOCOL_ERROR;
+ }
+ else
+ {
+ BerElement *ber= ber_init( psbvp );
+ if ( ber == NULL )
+ {
+ rc= LDAP_OPERATIONS_ERROR;
+ }
+ else
+ {
+ if ( ber_scanf( ber, "{e", mode ) == LBER_ERROR )
+ {
+ rc= LDAP_PROTOCOL_ERROR;
+ } else if ( ber_scanf( ber, "a", cookie ) != LBER_ERROR )
+ ber_scanf( ber, "b}", reload );
+
+ /* the ber encoding is no longer needed */
+ ber_free(ber,1);
+ }
+ }
+
+ return( rc );
+}
+
+char *
+sync_nsuniqueid2uuid(const char *nsuniqueid)
+{
+ char *uuid;
+ char u[17];
+
+ u[0] = slapi_str_to_u8(nsuniqueid);
+ u[1] = slapi_str_to_u8(nsuniqueid+2);
+ u[2] = slapi_str_to_u8(nsuniqueid+4);
+ u[3] = slapi_str_to_u8(nsuniqueid+6);
+
+ u[4] = slapi_str_to_u8(nsuniqueid+9);
+ u[5] = slapi_str_to_u8(nsuniqueid+11);
+ u[6] = slapi_str_to_u8(nsuniqueid+13);
+ u[7] = slapi_str_to_u8(nsuniqueid+15);
+
+ u[8] = slapi_str_to_u8(nsuniqueid+18);
+ u[9] = slapi_str_to_u8(nsuniqueid+20);
+ u[10] = slapi_str_to_u8(nsuniqueid+22);
+ u[11] = slapi_str_to_u8(nsuniqueid+24);
+
+ u[12] = slapi_str_to_u8(nsuniqueid+27);
+ u[13] = slapi_str_to_u8(nsuniqueid+29);
+ u[14] = slapi_str_to_u8(nsuniqueid+31);
+ u[15] = slapi_str_to_u8(nsuniqueid+33);
+
+ u[16] = '\0';
+
+ uuid = slapi_ch_smprintf("%s",(char *)u);
+
+ return(uuid);
+}
+
+/*
+ * syncStateValue ::= SEQUENCE {
+ * state ENUMERATED {
+ * present (0),
+ * add (1),
+ * modify (2),
+ * delete (3)
+ * },
+ * entryUUID syncUUID,
+ * cookie syncCookie OPTIONAL
+ * }
+ *
+ */
+int
+sync_create_state_control( Slapi_Entry *e, LDAPControl **ctrlp, int type, Sync_Cookie *cookie)
+{
+ int rc;
+ BerElement *ber;
+ struct berval *bvp;
+ char *uuid;
+ Slapi_Attr *attr;
+ Slapi_Value *val;
+
+ if ( ctrlp == NULL || ( ber = der_alloc()) == NULL ) {
+ return( LDAP_OPERATIONS_ERROR );
+ }
+
+ *ctrlp = NULL;
+
+ slapi_entry_attr_find(e, SLAPI_ATTR_UNIQUEID, &attr);
+ slapi_attr_first_value(attr, &val);
+ uuid = sync_nsuniqueid2uuid(slapi_value_get_string(val));
+ if (( rc = ber_printf( ber, "{eo", type , uuid, 16 )) != -1 ) {
+ if (cookie) {
+ char *cookiestr = sync_cookie2str(cookie);
+ rc = ber_printf( ber, "s}", cookiestr);
+ slapi_ch_free((void **)&cookiestr);
+ } else {
+ rc = ber_printf( ber, "}");
+
+ }
+ }
+ if (rc != -1) {
+ rc = ber_flatten( ber, &bvp );
+ }
+ ber_free( ber, 1 );
+ slapi_ch_free((void **)&uuid);
+
+ if ( rc == -1 ) {
+ return( LDAP_OPERATIONS_ERROR );
+ }
+
+ *ctrlp = (LDAPControl *)slapi_ch_malloc( sizeof( LDAPControl ));
+ (*ctrlp)->ldctl_iscritical = 0;
+ (*ctrlp)->ldctl_oid = slapi_ch_strdup( LDAP_CONTROL_SYNC_STATE );
+ (*ctrlp)->ldctl_value = *bvp; /* struct copy */
+
+ bvp->bv_val = NULL;
+ ber_bvfree( bvp );
+
+ return (LDAP_SUCCESS);
+}
+
+/*
+ * syncDoneValue ::= SEQUENCE {
+ * cookie syncCookie OPTIONAL
+ * refreshDeletes BOOLEAN DEFAULT FALSE
+ * }
+ *
+ */
+int
+sync_create_sync_done_control( LDAPControl **ctrlp, int refresh, char *cookie)
+{
+ int rc;
+ BerElement *ber;
+ struct berval *bvp;
+
+ if ( ctrlp == NULL || ( ber = der_alloc()) == NULL ) {
+ return( LDAP_OPERATIONS_ERROR );
+ }
+
+ *ctrlp = NULL;
+
+ if (cookie) {
+ if (( rc = ber_printf( ber, "{s", cookie)) != -1 ) {
+ if (refresh) {
+ rc = ber_printf( ber, "e}", refresh);
+ } else {
+ rc = ber_printf( ber, "}");
+ }
+ }
+ } else {
+ if (refresh) {
+ rc = ber_printf( ber, "{e}", refresh);
+ } else {
+ rc = ber_printf( ber, "{}");
+ }
+ }
+ if (rc != -1) {
+ rc = ber_flatten( ber, &bvp );
+ }
+ ber_free( ber, 1 );
+
+ if ( rc == -1 ) {
+ return( LDAP_OPERATIONS_ERROR );
+ }
+
+ *ctrlp = (LDAPControl *)slapi_ch_malloc( sizeof( LDAPControl ));
+ (*ctrlp)->ldctl_iscritical = 0;
+ (*ctrlp)->ldctl_oid = slapi_ch_strdup( LDAP_CONTROL_SYNC_DONE );
+ (*ctrlp)->ldctl_value = *bvp; /* struct copy */
+
+ bvp->bv_val = NULL;
+ ber_bvfree( bvp );
+
+ return (LDAP_SUCCESS);
+
+}
+
+char *
+sync_cookie2str(Sync_Cookie *cookie)
+{
+ char *cookiestr = NULL;
+
+ if (cookie) {
+ cookiestr = slapi_ch_smprintf("%s#%s#%d",
+ cookie->cookie_server_signature,
+ cookie->cookie_client_signature,
+ cookie->cookie_change_info);
+ }
+ return(cookiestr);
+}
+
+int
+sync_intermediate_msg (Slapi_PBlock *pb, int tag, Sync_Cookie *cookie, char **uuids)
+{
+ int rc;
+ struct berval *syncInfo;
+ LDAPControl *ctrlp = NULL;
+ char *cookiestr = sync_cookie2str(cookie);
+
+ syncInfo = create_syncinfo_value(tag, cookiestr, (const char **)uuids);
+
+ rc = slapi_send_ldap_intermediate( pb, &ctrlp, LDAP_SYNC_INFO, syncInfo);
+ slapi_ch_free((void **)&cookiestr);
+ ber_bvfree(syncInfo);
+ return (rc);
+}
+
+int sync_result_msg (Slapi_PBlock *pb, Sync_Cookie *cookie)
+{
+ int rc = 0;
+ char *cookiestr = sync_cookie2str(cookie);
+
+ LDAPControl **ctrl = (LDAPControl **)slapi_ch_calloc(2, sizeof (LDAPControl *));
+ sync_create_sync_done_control( &ctrl[0], 0, cookiestr);
+ slapi_pblock_set(pb, SLAPI_RESCONTROLS, ctrl);
+ slapi_send_ldap_result(pb, 0, NULL, NULL, 0, NULL );
+
+ slapi_ch_free((void **)&cookiestr);
+ return (rc);
+}
+
+int sync_result_err (Slapi_PBlock *pb, int err, char *msg)
+{
+ int rc = 0;
+
+ slapi_send_ldap_result(pb, err, NULL, msg, 0, NULL );
+
+ return (rc);
+}
+
+static struct berval *
+create_syncinfo_value( int type, const char *cookie, const char **uuids)
+{
+ BerElement *ber;
+ struct berval *bvp = NULL;
+
+ if ( ( ber = der_alloc() ) == NULL ) {
+ return( NULL );
+ }
+
+ switch (type) {
+ case LDAP_TAG_SYNC_NEW_COOKIE:
+ ber_printf(ber, "to", type, cookie);
+ break;
+ case LDAP_TAG_SYNC_REFRESH_DELETE:
+ case LDAP_TAG_SYNC_REFRESH_PRESENT:
+ ber_printf(ber, "t{", type);
+ if (cookie)
+ ber_printf(ber, "s", cookie);
+ /* ber_printf(ber, "b",1); */
+ ber_printf(ber, "}");
+ break;
+ case LDAP_TAG_SYNC_ID_SET:
+ ber_printf(ber, "t{", type);
+ if (cookie)
+ ber_printf(ber, "s", cookie);
+ if (uuids)
+ ber_printf(ber, "b[v]", 1, uuids);
+ ber_printf(ber, "}");
+ break;
+ default:
+ break;
+ }
+ ber_flatten( ber, &bvp );
+ ber_free( ber, 1 );
+
+ return( bvp );
+}
+
+static int
+sync_handle_cnum_entry(Slapi_Entry *e, void *cb_data)
+{
+ int rc = 0;
+ Sync_CallBackData *cb = (Sync_CallBackData *)cb_data;
+ Slapi_Value *sval=NULL;
+ const struct berval *value;
+
+ cb->changenr = 0;
+
+ if ( NULL != e ) {
+ Slapi_Attr *chattr = NULL;
+ sval = NULL;
+ value = NULL;
+ if ( slapi_entry_attr_find( e, CL_ATTR_CHANGENUMBER, &chattr ) == 0 ) {
+ slapi_attr_first_value( chattr,&sval );
+ if ( NULL != sval ) {
+ value = slapi_value_get_berval ( sval );
+ if( NULL != value && NULL != value->bv_val &&
+ '\0' != value->bv_val[0]) {
+ cb->changenr = sync_number2int(value->bv_val);
+ }
+ }
+ }
+ }
+ return (rc);
+}
+
+/*
+ * a cookie is used to synchronize client server sessions,
+ * it consist of three parts
+ * -- server id, client should only sync with one server
+ * -- client id, client should use same bind dn, and srch params
+ * -- change info, kind of state info like csn, ruv,
+ * in the first implementation use changenumber from retro cl
+ *
+ * syntax: <server-id>#<client-id>#change
+ *
+ */
+static char *
+sync_cookie_get_server_info(Slapi_PBlock *pb)
+{
+ char *info_enc;
+ int rc = 0;
+ Slapi_Entry **entries;
+ Slapi_PBlock *srch_pb = NULL;
+ char *host = NULL;
+ char *port = NULL;
+ char *server_attrs[] = {"nsslapd-localhost", "nsslapd-port", NULL};
+
+ srch_pb = slapi_pblock_new ();
+ slapi_search_internal_set_pb (srch_pb, "cn=config", LDAP_SCOPE_BASE,
+ "objectclass=*", server_attrs, 0, NULL, NULL,
+ plugin_get_default_component_id(), 0);
+ slapi_search_internal_pb (srch_pb);
+ slapi_pblock_get(srch_pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
+ if (rc != 0)
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, SYNC_PLUGIN_SUBSYSTEM, "sync_cookie_get_server_info: "
+ "unable to read server configuration: error %d\n", rc);
+ }
+ else
+ {
+ slapi_pblock_get(srch_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
+ if (NULL == entries || NULL == entries[0])
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, SYNC_PLUGIN_SUBSYSTEM, "sync_cookie_get_server_info: "
+ "server configuration missing\n");
+ rc = -1;
+ }
+ else
+ {
+ host = slapi_entry_attr_get_charptr(entries[0], "nsslapd-localhost");
+ port = slapi_entry_attr_get_charptr(entries[0], "nsslapd-port");
+ }
+ }
+ info_enc = slapi_ch_smprintf("%s:%s",host?host:"nohost",port?port:"noport");
+
+ slapi_ch_free ((void**)&host);
+ slapi_ch_free ((void**)&port);
+ slapi_free_search_results_internal(srch_pb);
+ slapi_pblock_destroy (srch_pb);
+ return(info_enc);
+}
+
+static char *
+sync_cookie_get_client_info(Slapi_PBlock *pb)
+{
+ char *targetdn;
+ char *strfilter;
+ char *clientdn;
+ char *clientinfo;
+
+ slapi_pblock_get(pb, SLAPI_TARGET_DN, &targetdn);
+ slapi_pblock_get(pb, SLAPI_SEARCH_STRFILTER, &strfilter);
+ slapi_pblock_get(pb, SLAPI_REQUESTOR_DN, &clientdn);
+ clientinfo = slapi_ch_smprintf("%s:%s:%s",clientdn,targetdn,strfilter);
+ return (clientinfo);
+}
+static int
+sync_cookie_get_change_number(int lastnr, const char *uniqueid)
+{
+ Slapi_PBlock *srch_pb;
+ Slapi_Entry **entries;
+ Slapi_Entry *cl_entry;
+ int rv;
+ int newnr = -1;
+ char *filter = slapi_ch_smprintf("(&(changenumber>=%d)(targetuniqueid=%s))",lastnr,uniqueid);
+
+ srch_pb = slapi_pblock_new();
+ slapi_search_internal_set_pb(srch_pb, CL_SRCH_BASE,
+ LDAP_SCOPE_SUBTREE, filter,
+ NULL, 0, NULL, NULL, plugin_get_default_component_id(), 0);
+ slapi_search_internal_pb(srch_pb);
+ slapi_pblock_get(srch_pb, SLAPI_PLUGIN_INTOP_RESULT, &rv);
+ if ( rv == LDAP_SUCCESS) {
+ slapi_pblock_get(srch_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
+ if (entries && *entries) {
+ Slapi_Attr *attr;
+ Slapi_Value *val;
+ cl_entry = *entries; /* only use teh first one */
+ slapi_entry_attr_find(cl_entry, CL_ATTR_CHANGENUMBER, &attr);
+ slapi_attr_first_value(attr, &val);
+ newnr = sync_number2int((char *)slapi_value_get_string(val));
+ }
+ }
+
+ slapi_free_search_results_internal(srch_pb);
+ slapi_pblock_destroy(srch_pb);
+ slapi_ch_free((void **)&filter);
+ return (newnr);
+}
+
+static int
+sync_cookie_get_change_info(Sync_CallBackData *scbd)
+{
+ Slapi_PBlock *seq_pb;
+ char *base;
+ char *attrname;
+ int rc;
+
+ base = slapi_ch_strdup("cn=changelog");
+ attrname = slapi_ch_strdup("changenumber");
+
+ seq_pb = slapi_pblock_new();
+ slapi_pblock_init(seq_pb);
+
+ slapi_seq_internal_set_pb(seq_pb, base, SLAPI_SEQ_LAST, attrname, NULL, NULL, 0, 0,
+ plugin_get_default_component_id(), 0);
+
+ rc = slapi_seq_internal_callback_pb (seq_pb, scbd, NULL, sync_handle_cnum_entry, NULL);
+ slapi_pblock_destroy(seq_pb);
+
+ slapi_ch_free((void **)&attrname);
+ slapi_ch_free((void **)&base);
+
+ return (rc);
+
+}
+
+Sync_Cookie *
+sync_cookie_create (Slapi_PBlock *pb)
+{
+
+ Sync_CallBackData scbd;
+ int rc;
+ Sync_Cookie *sc = (Sync_Cookie *)slapi_ch_malloc(sizeof(Sync_Cookie));
+
+
+ rc = sync_cookie_get_change_info (&scbd);
+
+ if (rc == 0) {
+ sc->cookie_server_signature = sync_cookie_get_server_info(pb);
+ sc->cookie_client_signature = sync_cookie_get_client_info(pb);
+ sc->cookie_change_info = scbd.changenr;
+ } else {
+ slapi_ch_free ((void **)&sc);
+ sc = NULL;
+ }
+
+ return (sc);
+}
+
+void sync_cookie_update (Sync_Cookie *sc, Slapi_Entry *ec)
+{
+ const char *uniqueid = NULL;
+ Slapi_Attr *attr;
+ Slapi_Value *val;
+
+ slapi_entry_attr_find(ec, SLAPI_ATTR_UNIQUEID, &attr);
+ slapi_attr_first_value(attr, &val);
+ uniqueid = slapi_value_get_string(val);
+
+ sc->cookie_change_info = sync_cookie_get_change_number (sc->cookie_change_info, uniqueid);
+}
+
+Sync_Cookie *
+sync_cookie_parse (char *cookie)
+{
+ char *p, *q;
+ Sync_Cookie *sc;
+
+ if (cookie == NULL || *cookie == '\0' ) {
+ return NULL;
+ }
+
+ p = q = cookie;
+ sc = (Sync_Cookie *)slapi_ch_malloc(sizeof(Sync_Cookie));
+
+ sc->cookie_client_signature = NULL;
+ sc->cookie_server_signature = NULL;
+ sc->cookie_change_info = -1;
+ p = strchr(q, '#');
+ if (p) {
+ *p = '\0';
+ sc->cookie_server_signature = slapi_ch_strdup(q);
+ q = p + 1;
+ p = strchr(q, '#');
+ if (p) {
+ *p = '\0';
+ sc->cookie_client_signature = slapi_ch_strdup(q);
+ sc->cookie_change_info = sync_number2int(p+1);
+ }
+ }
+
+ return (sc);
+}
+
+int
+sync_cookie_isvalid (Sync_Cookie *testcookie, Sync_Cookie *refcookie)
+{
+ /* client and server info must match */
+ if (strcmp(testcookie->cookie_client_signature,refcookie->cookie_client_signature) ||
+ strcmp(testcookie->cookie_server_signature,refcookie->cookie_server_signature) ||
+ testcookie->cookie_change_info == -1 ||
+ testcookie->cookie_change_info > refcookie->cookie_change_info )
+ return (0);
+ /* could add an additional check if the requested state in client cookie is still
+ * available. Accept any state request for now.
+ */
+ return (1);
+}
+
+void
+sync_cookie_free (Sync_Cookie **freecookie)
+{
+ if (*freecookie) {
+ slapi_ch_free((void **)&((*freecookie)->cookie_client_signature));
+ slapi_ch_free((void **)&((*freecookie)->cookie_server_signature));
+ slapi_ch_free((void **)freecookie);
+ }
+}
+
+int sync_is_active_scope (const Slapi_DN *dn, Slapi_PBlock *pb)
+{
+ int rc;
+ char *origbase = NULL;
+ Slapi_DN *base = NULL;
+ int scope;
+
+ slapi_pblock_get( pb, SLAPI_ORIGINAL_TARGET_DN, &origbase );
+ slapi_pblock_get( pb, SLAPI_SEARCH_TARGET_SDN, &base );
+ slapi_pblock_get( pb, SLAPI_SEARCH_SCOPE, &scope );
+ if (NULL == base) {
+ base = slapi_sdn_new_dn_byref(origbase);
+ slapi_pblock_set(pb, SLAPI_SEARCH_TARGET_SDN, base);
+ }
+ if ( slapi_sdn_scope_test(dn, base, scope )) {
+ rc = 1;
+ } else {
+ rc = 0;
+ }
+
+ return (rc);
+}
+
+int sync_is_active (Slapi_Entry *e, Slapi_PBlock *pb)
+{
+ if ( pb == NULL ) {
+ /* not yet initialized */
+ return(0);
+ } else {
+ /* check id entry is in scope of sync request */
+ return(sync_is_active_scope( slapi_entry_get_sdn_const(e),pb));
+ }
+}
+
+
+Slapi_PBlock *
+sync_pblock_copy(Slapi_PBlock *src)
+{
+ Slapi_Operation *operation;
+ Slapi_Connection *connection;
+ int *scope;
+ int *deref;
+ int *filter_normalized;
+ char *fstr;
+ char **attrs, **attrs_dup;
+ int *attrsonly;
+ int *isroot;
+ int *sizelimit;
+ int *timelimit;
+ struct slapdplugin *pi;
+
+
+ slapi_pblock_get( src, SLAPI_OPERATION, &operation );
+ slapi_pblock_get( src, SLAPI_CONNECTION, &connection );
+ slapi_pblock_get( src, SLAPI_SEARCH_SCOPE, &scope );
+ slapi_pblock_get( src, SLAPI_SEARCH_DEREF, &deref );
+ slapi_pblock_get( src, SLAPI_PLUGIN_SYNTAX_FILTER_NORMALIZED, &filter_normalized );
+ slapi_pblock_get( src, SLAPI_SEARCH_STRFILTER, &fstr );
+ slapi_pblock_get( src, SLAPI_SEARCH_ATTRS, &attrs );
+ slapi_pblock_get( src, SLAPI_SEARCH_ATTRSONLY, &attrsonly );
+ slapi_pblock_get( src, SLAPI_REQUESTOR_ISROOT, &isroot );
+ slapi_pblock_get( src, SLAPI_SEARCH_SIZELIMIT, &sizelimit );
+ slapi_pblock_get( src, SLAPI_SEARCH_TIMELIMIT, &timelimit );
+ slapi_pblock_get( src, SLAPI_PLUGIN, &pi);
+
+ Slapi_PBlock *dest = slapi_pblock_new();
+
+ slapi_pblock_set( dest, SLAPI_OPERATION, operation );
+ slapi_pblock_set( dest, SLAPI_CONNECTION, connection );
+ slapi_pblock_set( dest, SLAPI_SEARCH_SCOPE, &scope );
+ slapi_pblock_set( dest, SLAPI_SEARCH_DEREF, &deref );
+ slapi_pblock_set( dest, SLAPI_PLUGIN_SYNTAX_FILTER_NORMALIZED, &filter_normalized );
+ slapi_pblock_set( dest, SLAPI_SEARCH_STRFILTER, slapi_ch_strdup(fstr) );
+ attrs_dup = slapi_ch_array_dup(attrs);
+ slapi_pblock_set( dest, SLAPI_SEARCH_ATTRS, attrs_dup );
+ slapi_pblock_set( dest, SLAPI_SEARCH_ATTRSONLY, &attrsonly );
+ slapi_pblock_set( dest, SLAPI_REQUESTOR_ISROOT, &isroot );
+ slapi_pblock_set( dest, SLAPI_SEARCH_SIZELIMIT, &sizelimit );
+ slapi_pblock_set( dest, SLAPI_SEARCH_TIMELIMIT, &timelimit );
+ slapi_pblock_set( dest, SLAPI_PLUGIN, pi);
+
+ return dest;
+}
+
+int sync_number2int(char *chgnrstr)
+{
+ char *end;
+ int nr;
+ nr = strtoul(chgnrstr, &end, 10);
+ if ( *end == '\0') {
+ return (nr);
+ } else {
+ return (-1);
+ }
+}
diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c
index f5fa51b..92352e0 100644
--- a/ldap/servers/slapd/connection.c
+++ b/ldap/servers/slapd/connection.c
@@ -3015,7 +3015,12 @@ connection_abandon_operations( Connection *c )
/* abandon the operation only if it is not yet
completed (i.e., no result has been sent yet to
the client */
- if ( op->o_status != SLAPI_OP_STATUS_RESULT_SENT ) {
+ /* sync repl uses the persist mode, and it cannot prevent
+ * setting o_status, but has to be abandonned
+ * handle it here until a better solution is found
+ */
+ if ( op->o_status != SLAPI_OP_STATUS_RESULT_SENT ||
+ op->o_flags & OP_FLAG_PS ) {
op->o_status = SLAPI_OP_STATUS_ABANDONED;
}
}
diff --git a/ldap/servers/slapd/libslapd.def b/ldap/servers/slapd/libslapd.def
index 4b7cd7b..150147b 100644
--- a/ldap/servers/slapd/libslapd.def
+++ b/ldap/servers/slapd/libslapd.def
@@ -1200,3 +1200,7 @@ EXPORTS
config_get_pw_mintokenlength @1207
slapi_check_account_lock @1208
slapi_is_ldapi_conn @1209
+; slapi connection functions
+ slapi_connection_acquire @1211
+ slapi_connection_remove_operation @1212
+
diff --git a/ldap/servers/slapd/operation.c b/ldap/servers/slapd/operation.c
index 8ac413f..1c5c9b5 100644
--- a/ldap/servers/slapd/operation.c
+++ b/ldap/servers/slapd/operation.c
@@ -49,6 +49,7 @@
#include <sys/socket.h>
#endif
#include "slap.h"
+#include "fe.h"
int
slapi_op_abandoned( Slapi_PBlock *pb )
@@ -550,3 +551,60 @@ void operation_parameters_free(struct slapi_operation_parameters **sop)
slapi_ch_free ((void**)sop);
}
}
+
+int slapi_connection_acquire(Slapi_Connection *conn)
+{
+ int rc;
+
+ PR_Lock(conn->c_mutex);
+ /* rc = connection_acquire_nolock(conn); */
+ /* connection in the closing state can't be acquired */
+ if (conn->c_flags & CONN_FLAG_CLOSING)
+ {
+ /* This may happen while other threads are still working on this connection */
+ slapi_log_error(SLAPI_LOG_FATAL, "connection",
+ "conn=%" NSPRIu64 " fd=%d Attempt to acquire connection in the closing state\n",
+ (long long unsigned int)conn->c_connid, conn->c_sd);
+ rc = -1;
+ }
+ else
+ {
+ conn->c_refcnt++;
+ rc = 0;
+ }
+ PR_Unlock(conn->c_mutex);
+ return(rc);
+}
+
+int
+slapi_connection_remove_operation( Slapi_PBlock *pb, Slapi_Connection *conn, Slapi_Operation *op, int release)
+{
+ int rc = 0;
+ Slapi_Operation **olist= &conn->c_ops;
+ Slapi_Operation **tmp;
+ PR_Lock( conn->c_mutex );
+ /* connection_remove_operation_ext(pb, conn,op); */
+ for ( tmp = olist; *tmp != NULL && *tmp != op; tmp = &(*tmp)->o_next )
+ ; /* NULL */
+ if ( *tmp == NULL ) {
+ LDAPDebug( LDAP_DEBUG_ANY, "connection_remove_operation: can't find op %d for conn %" NSPRIu64 "\n",
+ (int)op->o_msgid, conn->c_connid, 0 );
+ } else {
+ *tmp = (*tmp)->o_next;
+ }
+
+ if (release) {
+ /* connection_release_nolock(conn); */
+ if (conn->c_refcnt <= 0) {
+ slapi_log_error(SLAPI_LOG_FATAL, "connection",
+ "conn=%" NSPRIu64 " fd=%d Attempt to release connection that is not acquired\n",
+ (long long unsigned int)conn->c_connid, conn->c_sd);
+ rc = -1;
+ } else {
+ conn->c_refcnt--;
+ rc = 0;
+ }
+ }
+ PR_Unlock( conn->c_mutex );
+ return (rc);
+}
diff --git a/ldap/servers/slapd/plugin.c b/ldap/servers/slapd/plugin.c
index aa33b02..66b011b 100644
--- a/ldap/servers/slapd/plugin.c
+++ b/ldap/servers/slapd/plugin.c
@@ -586,6 +586,15 @@ plugin_get_pwd_storage_scheme_list(int index)
return( names_list );
}
+int slapi_send_ldap_intermediate( Slapi_PBlock *pb, LDAPControl **ectrls,
+ char *responseName, struct berval *responseValue)
+{
+ /* no SLAPI_PLUGIN_DB_INTERMEDIATE_FN defined
+ * always directly call slapd_ function
+ */
+ return send_ldap_intermediate(pb, ectrls, responseName, responseValue);
+}
+
int
slapi_send_ldap_search_entry( Slapi_PBlock *pb, Slapi_Entry *e, LDAPControl **ectrls,
char **attrs, int attrsonly )
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index 95bfafd..e256728 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -958,6 +958,8 @@ int send_ldap_search_entry_ext( Slapi_PBlock *pb, Slapi_Entry *e, LDAPControl **
char **attrs, int attrsonly, int send_result, int nentries, struct berval **urls );
void send_ldap_result_ext( Slapi_PBlock *pb, int err, char *matched, char *text,
int nentries, struct berval **urls, BerElement *ber );
+int send_ldap_intermediate( Slapi_PBlock *pb, LDAPControl **ectrls,
+ char *responseName, struct berval *responseValue);
void send_nobackend_ldap_result( Slapi_PBlock *pb );
int send_ldap_referral( Slapi_PBlock *pb, Slapi_Entry *e, struct berval **refs,
struct berval ***urls );
diff --git a/ldap/servers/slapd/result.c b/ldap/servers/slapd/result.c
index f520e6b..655717f 100644
--- a/ldap/servers/slapd/result.c
+++ b/ldap/servers/slapd/result.c
@@ -82,6 +82,7 @@ static char * op_to_string(int tag);
#define _LDAP_SEND_RESULT 0
#define _LDAP_SEND_REFERRAL 1
#define _LDAP_SEND_ENTRY 2
+#define _LDAP_SEND_INTERMED 4
#define SLAPI_SEND_VATTR_FLAG_REALONLY 0x01
#define SLAPI_SEND_VATTR_FLAG_VIRTUALONLY 0x02
@@ -223,6 +224,79 @@ send_ldap_result(
send_ldap_result_ext(pb, err, matched, text, nentries, urls, NULL);
}
+int send_ldap_intermediate( Slapi_PBlock *pb, LDAPControl **ectrls,
+ char *responseName, struct berval *responseValue)
+{
+ ber_tag_t tag;
+ BerElement *ber;
+ Slapi_Connection *connection;
+ Slapi_Operation *operation;
+ int rc = 0;
+ int logit = 0;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> send_ldap_intermediate\n", 0, 0, 0 );
+ slapi_pblock_get (pb, SLAPI_OPERATION, &operation);
+ slapi_pblock_get (pb, SLAPI_CONNECTION, &connection);
+
+ if (operation->o_status == SLAPI_OP_STATUS_RESULT_SENT) {
+ return(rc); /* result already sent */
+ }
+ tag = LDAP_RES_INTERMEDIATE;
+ if ( (ber = der_alloc()) == NULL ) {
+ LDAPDebug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
+ goto log_and_return;
+ }
+ /* add the intermediate message */
+ rc = ber_printf( ber, "{it{", operation->o_msgid, tag);
+ /* print responsename */
+ rc = ber_printf ( ber, "ts", LDAP_TAG_IM_RES_OID, responseName);
+ /* print responsevalue */
+ rc = ber_printf ( ber, "tO", LDAP_TAG_IM_RES_VALUE, responseValue);
+
+
+
+ if ( rc != LBER_ERROR ) {
+ rc = ber_printf( ber, "}" ); /* one more } to come */
+ }
+
+ if ( ectrls != NULL
+ && connection->c_ldapversion >= LDAP_VERSION3
+ && write_controls( ber, ectrls ) != 0 ) {
+ rc = (int)LBER_ERROR;
+ }
+
+ if ( rc != LBER_ERROR ) { /* end the LDAPMessage sequence */
+ rc = ber_put_seq( ber );
+ }
+ if ( rc == LBER_ERROR ) {
+ LDAPDebug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
+ ber_free( ber, 1 /* freebuf */ );
+ goto log_and_return;
+ }
+
+ /* write only one pdu at a time - wait til it's our turn */
+ if ( flush_ber( pb, connection, operation, ber, _LDAP_SEND_INTERMED ) == 0 ) {
+ logit = 1;
+ }
+log_and_return:
+ /* operation->o_status = SLAPI_OP_STATUS_RESULT_SENT;
+ * there could be multiple intermediate messages on
+ * the same connection, unlike in send_result do not
+ * set o_status
+ */
+
+ if ( logit && operation_is_flag_set( operation,
+ OP_FLAG_ACTION_LOG_ACCESS )) {
+ log_result( pb, operation, rc, tag, 0 );
+ }
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= send_ldap_intermediate\n", 0, 0, 0 );
+ if (rc == LBER_ERROR) {
+ return(1);
+ } else {
+ return(0);
+ }
+}
static int
check_and_send_extended_result(Slapi_PBlock *pb, ber_tag_t tag, BerElement *ber)
@@ -1555,7 +1629,7 @@ send_ldap_search_entry_ext(
}
/* if the client explicitly specified a list of attributes look through each attribute requested */
- if( (rc == 0) && (attrs!=NULL)) {
+ if( (rc == 0) && (attrs!=NULL) && !noattrs) {
rc = send_specific_attrs(e,attrs,op,pb,ber,attrsonly,conn->c_ldapversion,dontsendattr,real_attrs_only);
}
@@ -1695,6 +1769,8 @@ flush_ber(
case _LDAP_SEND_REFERRAL:
rc = plugin_call_plugins( pb, SLAPI_PLUGIN_PRE_REFERRAL_FN );
break;
+ case _LDAP_SEND_INTERMED:
+ break; /* not a plugin entry point */
}
if ( rc != 0 ) {
@@ -1764,6 +1840,8 @@ flush_ber(
slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsEntriesReturned);
plugin_call_plugins( pb, SLAPI_PLUGIN_POST_ENTRY_FN );
break;
+ case _LDAP_SEND_INTERMED:
+ break; /* not a plugin entry point */
}
return( rc );
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index e02a125..f904267 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -4966,6 +4966,13 @@ char *slapi_op_type_to_string(unsigned long type);
int slapi_op_internal( Slapi_PBlock *pb );
/*
+ * connection routines
+ */
+
+int slapi_connection_acquire(Slapi_Connection *conn);
+int slapi_connection_remove_operation( Slapi_PBlock *pb, Slapi_Connection *conn, Slapi_Operation *op, int release);
+
+/*
* LDAPMod manipulation routines
*/
Slapi_Mods* slapi_mods_new( void );
@@ -5127,6 +5134,8 @@ void slapi_send_ldap_result( Slapi_PBlock *pb, int err, char *matched,
char *text, int nentries, struct berval **urls );
int slapi_send_ldap_referral( Slapi_PBlock *pb, Slapi_Entry *e,
struct berval **refs, struct berval ***urls );
+int slapi_send_ldap_intermediate( Slapi_PBlock *pb, LDAPControl **ectrls,
+ char *responseName, struct berval *responseValue);
typedef int (*send_ldap_search_entry_fn_ptr_t)( Slapi_PBlock *pb,
Slapi_Entry *e, LDAPControl **ectrls, char **attrs, int attrsonly );
typedef void (*send_ldap_result_fn_ptr_t)( Slapi_PBlock *pb, int err,
10 years, 6 months
ldap/admin
by Richard Allen Megginson
ldap/admin/src/logconv.pl | 775 +++++++++++++++++++---------------------------
1 file changed, 333 insertions(+), 442 deletions(-)
New commits:
commit 4d20922423c9e22c858e0be7dd317591631cf357
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Tue Jul 23 17:05:32 2013 -0600
Ticket #47501 logconv.pl uses /var/tmp for BDB temp files
https://fedorahosted.org/389/ticket/47501
Reviewed by: mreynolds (Thanks!)
Branch: master
Fix Description: Tied arrays with DB_RECNO require a backing text file. By
default this goes in /var/tmp. This can be controlled with RECNOINFO bfname.
However, the use of arrays was killing performance. This patch replaces
all arrays with tied hashes. In addition, this patch fixes the notes=U
handling to also handle notes=U,P and notes=A,P
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
diff --git a/ldap/admin/src/logconv.pl b/ldap/admin/src/logconv.pl
index 3a6fa01..ca07a3a 100755
--- a/ldap/admin/src/logconv.pl
+++ b/ldap/admin/src/logconv.pl
@@ -67,7 +67,7 @@ if ($#ARGV < 0){;
my $file_count = 0;
my $arg_count = 0;
-my $logversion = "7.0";
+my $logversion = "8.0";
my $sizeCount = "20";
my $startFlag = 0;
my $startTime = 0;
@@ -76,6 +76,8 @@ my $endTime = 0;
my $reportStats = "";
my $dataLocation = "/tmp";
my $startTLSoid = "1.3.6.1.4.1.1466.20037";
+my @statnames=qw(last last_str results srch add mod modrdn moddn cmp del abandon
+ conns sslconns bind anonbind unbind notesA notesU etime);
my $s_stats = new_stats_block( );
my $m_stats = new_stats_block( );
my $verb = "no";
@@ -95,8 +97,6 @@ my %connList;
my %bindReport;
my @vlvconn;
my @vlvop;
-my @start_time_of_connection;
-my @end_time_of_connection;
my @fds;
my $fdds = 0;
my $reportBinds = "no";
@@ -179,7 +179,7 @@ if ($sizeCount eq "all"){$sizeCount = "100000";}
#######################################
# #
-# Initialize Arrays and variables #
+# Initialize Hashes and variables #
# #
#######################################
@@ -255,21 +255,17 @@ map {$conn{$_} = $_} @conncodes;
# hash db-backed hashes
my @hashnames = qw(attr rc src rsrc excount conn_hash ip_hash conncount nentries
- filter base ds6xbadpwd saslmech bindlist etime oid);
+ filter base ds6xbadpwd saslmech bindlist etime oid
+ start_time_of_connection end_time_of_connection
+ notesa_conn_op notesu_conn_op etime_conn_op nentries_conn_op
+ optype_conn_op time_conn_op srch_conn_op del_conn_op mod_conn_op
+ mdn_conn_op cmp_conn_op bind_conn_op unbind_conn_op ext_conn_op
+ abandon_conn_op badpwd_conn_op);
# need per connection code ip address counts - so use a hash table
# for each connection code - key is ip, val is count
push @hashnames, @conncodes;
my $hashes = openHashFiles($dataLocation, @hashnames);
-# recno db-backed arrays/lists
-my @arraynames = qw(srchconn srchop delconn delop modconn modop addconn addop modrdnconn modrdnop
- cmpconn cmpop targetconn targetop msgid bindconn bindop binddn unbindconn unbindop
- extconn extop notesAetime notesAconn notesAop notesAtime notesAnentries
- notesUetime notesUconn notesUop notesUtime notesUnentries badpwdconn
- badpwdop badpwdip baseval baseconn baseop scopeval scopeconn scopeop
- filterval filterconn filterop);
-my $arrays = openArrayFiles($dataLocation, @arraynames);
-
$needCleanup = 1;
my @err;
@@ -636,6 +632,12 @@ Binds: @<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
.
write STDOUT;
+# format/write messes up emacs autoformatting - inserting this dummy function
+# fixes that
+sub dummy {
+ my $bar = shift;
+}
+
print "\n";
print "Proxied Auth Operations: $proxiedAuthCount\n";
print "Persistent Searches: $persistentSrchCount\n";
@@ -658,115 +660,75 @@ print "Unindexed Components: $unindexedSrchCountNotesU\n";
if ($verb eq "yes" || $usage =~ /u/){
if ($unindexedSrchCountNotesA > 0){
my $conn_hash = $hashes->{conn_hash};
- my $notesConn = $arrays->{notesAconn};
- my $notesOp = $arrays->{notesAop};
- my $notesEtime = $arrays->{notesAetime};
- my $notesTime = $arrays->{notesAtime};
- my $notesNentries = $arrays->{notesAnentries};
- my $base_val = $arrays->{baseval};
- my $base_conn = $arrays->{baseconn};
- my $base_op = $arrays->{baseop};
- my $scope_val = $arrays->{scopeval};
- my $scope_conn = $arrays->{scopeconn};
- my $scope_op = $arrays->{scopeop};
- my $filter_val = $arrays->{filterval};
- my $filter_conn = $arrays->{filterconn};
- my $filter_op = $arrays->{filterop};
- my $notesCount = "1";
+ my $notesa_conn_op = $hashes->{notesa_conn_op};
+ my $time_conn_op = $hashes->{time_conn_op};
+ my $etime_conn_op = $hashes->{etime_conn_op};
+ my $nentries_conn_op = $hashes->{nentries_conn_op};
+ my $base_conn_op = $hashes->{base_conn_op};
+ my $scope_conn_op = $hashes->{scope_conn_op};
+ my $filter_conn_op = $hashes->{filter_conn_op};
+
+ my $notesCount = 1;
my $unindexedIp;
-
- for (my $n = 0; $n < scalar(@{$notesEtime}); $n++){
- if(!$notesConn->[$n] || $notesConn->[$n] eq "" ||
- !$conn_hash->{$notesConn->[$n]} || $conn_hash->{$notesConn->[$n]} eq ""){
- $unindexedIp = "?";
+ while (my ($conn_op, $count) = each %{$notesa_conn_op}) {
+ my ($conn, $op) = split(",", $conn_op);
+ if (exists($conn_hash->{$conn}) && defined($conn_hash->{$conn})) {
+ $unindexedIp = $conn_hash->{$conn};
} else {
- $unindexedIp = $conn_hash->{$notesConn->[$n]};
+ $unindexedIp = "?";
}
- print "\n Unindexed Search #".$notesCount."\n"; $notesCount++;
- print " - Date/Time: $notesTime->[$n]\n";
- print " - Connection Number: $notesConn->[$n]\n";
- print " - Operation Number: $notesOp->[$n]\n";
- print " - Etime: $notesEtime->[$n]\n";
- print " - Nentries: $notesNentries->[$n]\n";
+ print "\n Unindexed Components #".$notesCount."\n"; $notesCount++;
+ print " - Date/Time: $time_conn_op->{$conn_op}\n";
+ print " - Connection Number: $conn\n";
+ print " - Operation Number: $op\n";
+ print " - Etime: $etime_conn_op->{$conn_op}\n";
+ print " - Nentries: $nentries_conn_op->{$conn_op}\n";
print " - IP Address: $unindexedIp\n";
-
- for (my $nnn = 0; $nnn < $baseCount; $nnn++){
- if(!$base_conn->[$nnn] || !$base_op->[$nnn]){ next; }
- if ($notesConn->[$n] eq $base_conn->[$nnn] && $notesOp->[$n] eq $base_op->[$nnn]){
- print " - Search Base: $base_val->[$nnn]\n";
- last;
- }
+ if (exists($base_conn_op->{$conn_op}) && defined($base_conn_op->{$conn_op})) {
+ print " - Search Base: $base_conn_op->{$conn_op}\n";
}
- for (my $nnn = 0; $nnn < $scopeCount; $nnn++){
- if(!$scope_conn->[$nnn] || !$scope_op->[$nnn]){ next; }
- if ($notesConn->[$n] eq $scope_conn->[$nnn] && $notesOp->[$n] eq $scope_op->[$nnn]){
- print " - Search Scope: $scope_val->[$nnn]\n";
- last;
- }
+ if (exists($scope_conn_op->{$conn_op}) && defined($scope_conn_op->{$conn_op})) {
+ print " - Search Scope: $scope_conn_op->{$conn_op}\n";
}
- for (my $nnn = 0; $nnn < $filterCount; $nnn++){
- if(!$filter_conn->[$nnn] || !$filter_op->[$nnn]){ next; }
- if ($notesConn->[$n] eq $filter_conn->[$nnn] && $notesOp->[$n] eq $filter_op->[$nnn]){
- print " - Search Filter: $filter_val->[$nnn]\n";
- last;
- }
+ if (exists($filter_conn_op->{$conn_op}) && defined($filter_conn_op->{$conn_op})) {
+ print " - Search Filter: $filter_conn_op->{$conn_op}\n";
}
}
}
if ($unindexedSrchCountNotesU > 0){
my $conn_hash = $hashes->{conn_hash};
- my $notesConn = $arrays->{notesUconn};
- my $notesOp = $arrays->{notesUop};
- my $notesEtime = $arrays->{notesUetime};
- my $notesTime = $arrays->{notesUtime};
- my $notesNentries = $arrays->{notesUnentries};
- my $base_val = $arrays->{baseval};
- my $base_conn = $arrays->{baseconn};
- my $base_op = $arrays->{baseop};
- my $scope_val = $arrays->{scopeval};
- my $scope_conn = $arrays->{scopeconn};
- my $scope_op = $arrays->{scopeop};
- my $filter_val = $arrays->{filterval};
- my $filter_conn = $arrays->{filterconn};
- my $filter_op = $arrays->{filterop};
-
- my $notesCount = "1";
+ my $notesu_conn_op = $hashes->{notesu_conn_op};
+ my $time_conn_op = $hashes->{time_conn_op};
+ my $etime_conn_op = $hashes->{etime_conn_op};
+ my $nentries_conn_op = $hashes->{nentries_conn_op};
+ my $base_conn_op = $hashes->{base_conn_op};
+ my $scope_conn_op = $hashes->{scope_conn_op};
+ my $filter_conn_op = $hashes->{filter_conn_op};
+
+ my $notesCount = 1;
my $unindexedIp;
- for (my $n = 0; $n < scalar(@{$notesEtime}); $n++){
- if(!$notesConn->[$n] || $notesConn->[$n] eq "" ||
- !$conn_hash->{$notesConn->[$n]} || $conn_hash->{$notesConn->[$n]} eq ""){
- $unindexedIp = "?";
+ while (my ($conn_op, $count) = each %{$notesu_conn_op}) {
+ my ($conn, $op) = split(",", $conn_op);
+ if (exists($conn_hash->{$conn}) && defined($conn_hash->{$conn})) {
+ $unindexedIp = $conn_hash->{$conn};
} else {
- $unindexedIp = $conn_hash->{$notesConn->[$n]};
+ $unindexedIp = "?";
}
print "\n Unindexed Components #".$notesCount."\n"; $notesCount++;
- print " - Date/Time: $notesTime->[$n]\n";
- print " - Connection Number: $notesConn->[$n]\n";
- print " - Operation Number: $notesOp->[$n]\n";
- print " - Etime: $notesEtime->[$n]\n";
- print " - Nentries: $notesNentries->[$n]\n";
+ print " - Date/Time: $time_conn_op->{$conn_op}\n";
+ print " - Connection Number: $conn\n";
+ print " - Operation Number: $op\n";
+ print " - Etime: $etime_conn_op->{$conn_op}\n";
+ print " - Nentries: $nentries_conn_op->{$conn_op}\n";
print " - IP Address: $unindexedIp\n";
-
- for (my $nnn = 0; $nnn < $baseCount; $nnn++){
- if(!$base_conn->[$nnn] || !$base_op->[$nnn]){ next; }
- if ($notesConn->[$n] eq $base_conn->[$nnn] && $notesOp->[$n] eq $base_op->[$nnn]){
- print " - Search Base: $base_val->[$nnn]\n";
- last;
- }
+ if (exists($base_conn_op->{$conn_op}) && defined($base_conn_op->{$conn_op})) {
+ print " - Search Base: $base_conn_op->{$conn_op}\n";
}
- for (my $nnn = 0; $nnn < $scopeCount; $nnn++){
- if(!$scope_conn->[$nnn] || !$scope_op->[$nnn]){ next; }
- if ($notesConn->[$n] eq $scope_conn->[$nnn] && $notesOp->[$n] eq $scope_op->[$nnn]){
- print " - Search Scope: $scope_val->[$nnn]\n";
- last;
- }
+ if (exists($scope_conn_op->{$conn_op}) && defined($scope_conn_op->{$conn_op})) {
+ print " - Search Scope: $scope_conn_op->{$conn_op}\n";
}
- for (my $nnn = 0; $nnn < $filterCount; $nnn++){
- if(!$filter_conn->[$nnn] || !$filter_op->[$nnn]){ next; }
- if ($notesConn->[$n] eq $filter_conn->[$nnn] && $notesOp->[$n] eq $filter_op->[$nnn]){
- print " - Search Filter: $filter_val->[$nnn]\n";
- last;
- }
+ if (exists($filter_conn_op->{$conn_op}) && defined($filter_conn_op->{$conn_op})) {
+ print " - Search Filter: $filter_conn_op->{$conn_op}\n";
}
}
}
@@ -800,7 +762,7 @@ if ($connResetByPeerCount > 0){
push @retext, sprintf " - %-4s (%2s) %-40s\n",$src->{$key},$conn{$key},$connmsg{$key};
}
}
- print @retext;
+ print @retext;
print "\n";
}
@@ -813,8 +775,8 @@ if ($resourceUnavailCount > 0){
if ($conn{$key} eq ""){$conn{$key} = "**Resource Issue**";}
push @rtext, sprintf " - %-4s (%2s) %-40s\n",$rsrc->{$key},$conn{$key},$connmsg{$key};
}
- }
- print @rtext;
+ }
+ print @rtext;
}
print "Max BER Size Exceeded: $maxBerSizeCount\n";
print "\n";
@@ -829,7 +791,7 @@ print " - SASL Binds: $saslBindCount\n";
if ($saslBindCount > 0){
my $saslmech = $hashes->{saslmech};
foreach my $saslb ( sort {$saslmech->{$b} <=> $saslmech->{$a} } (keys %{$saslmech}) ){
- printf " %-4s %-12s\n",$saslmech->{$saslb}, $saslb;
+ printf " %-4s %-12s\n",$saslmech->{$saslb}, $saslb;
}
}
@@ -914,13 +876,13 @@ if ($usage =~ /e/i || $verb eq "yes"){
for (my $i = 0; $i <= $#errtext; $i++){
$errtext[$i] =~ s/\n//g;
print "\n" . $errtext[$i];
- }
+ }
}
####################################
-# #
+# #
# Print Failed Logins #
-# #
+# #
####################################
if ($verb eq "yes" || $usage =~ /f/ ){
@@ -936,19 +898,20 @@ if ($verb eq "yes" || $usage =~ /f/ ){
$ds6loop++;
}
} else {
- my $bindVal = $arrays->{binddn};
- my $bindConn = $arrays->{bindconn};
- my $bindOp = $arrays->{bindop};
- my $badPasswordConn = $arrays->{badpwdconn};
- my $badPasswordOp = $arrays->{badpwdop};
- my $badPasswordIp = $arrays->{badpwdip};
+ # key is conn,op - val is binddn
+ my $bind_conn_op = $hashes->{bind_conn_op};
+ # key is conn,op - val is count
+ my $badpwd_conn_op = $hashes->{badpwd_conn_op};
+ # key is binddn - val is count
my %badPassword = ();
- for (my $ii =0 ; $ii < $badPwdCount; $ii++){
- for (my $i = 0; $i < $bindCount; $i++){
- if ($badPasswordConn->[$ii] eq $bindConn->[$i] && $badPasswordOp->[$ii] eq $bindOp->[$i] ){
- $badPassword{ $bindVal->[$i] }++;
- }
- }
+ my @badPasswordIp = ();
+ while (my ($conn_op, $count) = each %{$badpwd_conn_op}) {
+ my ($conn, $op) = split(",", $conn_op);
+ if (exists($bind_conn_op->{$conn_op}) && defined($bind_conn_op->{$conn_op})) {
+ my $binddn = $bind_conn_op->{$conn_op};
+ $badPassword{$binddn}++;
+ push @badPasswordIp, getIPfromConn($conn);
+ }
}
# sort the new hash of $badPassword{}
my $bpTotal = 0;
@@ -961,7 +924,7 @@ if ($verb eq "yes" || $usage =~ /f/ ){
}
print "\nFrom the IP address(s) :\n\n";
for (my $i=0; $i<$badPwdCount; $i++) {
- print "\t\t$badPasswordIp->[$i]\n";
+ print "\t\t$badPasswordIp[$i]\n";
}
if ($bpTotal > $badPwdCount){
print "\n** Warning : Wrongly reported failed login attempts : ". ($bpTotal - $badPwdCount) . "\n";
@@ -982,11 +945,11 @@ if ($connCodeCount > 0){
print "\n\n----- Total Connection Codes -----\n\n";
my $conncount = $hashes->{conncount};
my @conntext;
- foreach my $key (sort { $conncount->{$b} <=> $conncount->{$a} } keys %{$conncount}) {
- if ($conncount->{$key} > 0){
+ foreach my $key (sort { $conncount->{$b} <=> $conncount->{$a} } keys %{$conncount}) {
+ if ($conncount->{$key} > 0){
push @conntext, sprintf "%-4s %6s %-40s\n",$key,$conncount->{$key},$connmsg{ $key };
- }
- }
+ }
+ }
print @conntext;
}
}
@@ -1005,8 +968,8 @@ if ($usage =~ /i/i || $verb eq "yes"){
my $ip_count = ($#ipkeys + 1)-($#exxCount + 1);
my $ccount = 0;
if ($ip_count > 0){
- print "\n\n----- Top $sizeCount Clients -----\n\n";
- print "Number of Clients: $ip_count\n\n";
+ print "\n\n----- Top $sizeCount Clients -----\n\n";
+ print "Number of Clients: $ip_count\n\n";
foreach my $key (sort { $ip_hash->{$b} <=> $ip_hash->{$a} } @ipkeys) {
my $exc = "no";
if ($ccount > $sizeCount){ last;}
@@ -1021,7 +984,7 @@ if ($usage =~ /i/i || $verb eq "yes"){
my %counts;
map { $counts{$_} = $hashes->{$_}->{$key} if (defined($hashes->{$_}->{$key})) } @conncodes;
foreach my $code (sort { $counts{$b} <=> $counts{$a} } keys %counts) {
- if ($code eq 'count' ) { next; }
+ if ($code eq 'count' ) { next; }
printf "%10s - %s (%s)\n", $counts{ $code }, $code, $connmsg{ $code };
}
print "\n";
@@ -1042,14 +1005,14 @@ if ($usage =~ /b/i || $verb eq "yes"){
my $bind_count = $#bindkeys + 1;
if ($bind_count > 0){
print "\n\n----- Top $sizeCount Bind DN's -----\n\n";
- print "Number of Unique Bind DN's: $bind_count\n\n";
+ print "Number of Unique Bind DN's: $bind_count\n\n";
my $bindcount = 0;
foreach my $dn (sort { $bindlist->{$b} <=> $bindlist->{$a} } @bindkeys) {
- if ($bindcount < $sizeCount){
+ if ($bindcount < $sizeCount){
printf "%-8s %-40s\n", $bindlist->{ $dn },$dn;
} else {
- last;
- }
+ last;
+ }
$bindcount++;
}
}
@@ -1070,16 +1033,16 @@ if ($usage =~ /a/i || $verb eq "yes"){
print "Number of Unique Search Bases: $base_count\n\n";
my $basecount = 0;
foreach my $bas (sort { $base->{$b} <=> $base->{$a} } @basekeys) {
- if ($basecount < $sizeCount){
- printf "%-8s %-40s\n", $base->{ $bas },$bas;
- } else {
- last;
- }
- $basecount++;
+ if ($basecount < $sizeCount){
+ printf "%-8s %-40s\n", $base->{ $bas },$bas;
+ } else {
+ last;
+ }
+ $basecount++;
}
}
}
-
+
#########################################
# #
# Gather and process search filters #
@@ -1091,15 +1054,15 @@ if ($usage =~ /l/ || $verb eq "yes"){
my @filterkeys = keys %{$filter};
my $filter_count = $#filterkeys + 1;
if ($filter_count > 0){
- print "\n\n----- Top $sizeCount Search Filters -----\n";
+ print "\n\n----- Top $sizeCount Search Filters -----\n";
print "\nNumber of Unique Search Filters: $filter_count\n\n";
my $filtercount = 0;
foreach my $filt (sort { $filter->{$b} <=> $filter->{$a} } @filterkeys){
if ($filtercount < $sizeCount){
printf "%-8s %-40s\n", $filter->{$filt}, $filt;
} else {
- last;
- }
+ last;
+ }
$filtercount++;
}
}
@@ -1108,7 +1071,7 @@ if ($usage =~ /l/ || $verb eq "yes"){
#########################################
# #
# Gather and Process the unique etimes #
-# #
+# #
#########################################
my $first;
@@ -1139,7 +1102,7 @@ if ($usage =~ /t/i || $verb eq "yes"){
if ($eloop == $sizeCount) { last; }
printf "%-12s %-10s\n","etime=$et",$etime->{ $et };
$eloop++;
- }
+ }
}
#######################################
@@ -1156,7 +1119,7 @@ if ($usage =~ /n/i || $verb eq "yes"){
my $eloop = 0;
foreach my $nentry (sort { $b <=> $a } @nkeys){
if ($eloop == $sizeCount) { last; }
- printf "%-18s %12s\n","nentries=$nentry", $nentries->{ $nentry };
+ printf "%-18s %12s\n","nentries=$nentry", $nentries->{ $nentry };
$eloop++;
}
print "\n\n----- Top $sizeCount Most returned nentries -----\n\n";
@@ -1216,7 +1179,7 @@ if ($usage =~ /x/i || $verb eq "yes"){
}
############################################
-# #
+# #
# Print most commonly requested attributes #
# #
############################################
@@ -1235,7 +1198,7 @@ if ($usage =~ /r/i || $verb eq "yes"){
}
#############################
-# #
+# #
# abandoned operation stats #
# #
#############################
@@ -1244,66 +1207,49 @@ if ($usage =~ /g/i || $verb eq "yes"){
my $abandonTotal = $srchCount + $delCount + $modCount + $addCount + $modrdnCount + $bindCount + $extopCount + $cmpCount;
if ($verb eq "yes" && $abandonCount > 0 && $abandonTotal > 0){
my $conn_hash = $hashes->{conn_hash};
+ my $abandon_conn_op = $hashes->{abandon_conn_op};
+ my $srch_conn_op = $hashes->{srch_conn_op};
+ my $del_conn_op = $hashes->{del_conn_op};
+ my $add_conn_op = $hashes->{add_conn_op};
+ my $mod_conn_op = $hashes->{mod_conn_op};
+ my $cmp_conn_op = $hashes->{cmp_conn_op};
+ my $mdn_conn_op = $hashes->{mdn_conn_op};
+ my $bind_conn_op = $hashes->{bind_conn_op};
+ my $unbind_conn_op = $hashes->{unbind_conn_op};
+ my $ext_conn_op = $hashes->{ext_conn_op};
print "\n\n----- Abandon Request Stats -----\n\n";
- for (my $g = 0; $g < $abandonCount; $g++){
- my $conn = $arrays->{targetconn}->[$g];
- my $op = $arrays->{targetop}->[$g];
- my $msgid = $arrays->{msgid}->[$g];
- for (my $sc = 0; $sc < $srchCount; $sc++){
- if (($arrays->{srchconn}->[$sc] && $arrays->{srchop}->[$sc]) &&
- ($arrays->{srchconn}->[$sc] eq $conn && $arrays->{srchop}->[$sc] eq $op )){
- print " - SRCH conn=$conn op=$op msgid=$msgid client=$conn_hash->{$conn}\n";
- }
- }
- for (my $dc = 0; $dc < $delCount; $dc++){
- if (($arrays->{delconn}->[$dc] && $arrays->{delop}->[$dc]) &&
- ($arrays->{delconn}->[$dc] eq $conn && $arrays->{delop}->[$dc] eq $op)){
- print " - DEL conn=$conn op=$op msgid=$msgid client=$conn_hash->{$conn}\n";
- }
- }
- for (my $adc = 0; $adc < $addCount; $adc++){
- if (($arrays->{addconn}->[$adc] && $arrays->{addop}->[$adc]) &&
- ($arrays->{addconn}->[$adc] eq $conn && $arrays->{addop}->[$adc] eq $op)){
- print " - ADD conn=$conn op=$op msgid=$msgid client=$conn_hash->{$conn}\n";
- }
- }
- for (my $mc = 0; $mc < $modCount; $mc++){
- if (($arrays->{modconn}->[$mc] && $arrays->{modop}->[$mc]) &&
- ($arrays->{modconn}->[$mc] eq $conn && $arrays->{modop}->[$mc] eq $op)){
- print " - MOD conn=$conn op=$op msgid=$msgid client=$conn_hash->{$conn}\n";
- }
- }
- for (my $cc = 0; $cc < $cmpCount; $cc++){
- if (($arrays->{cmpconn}->[$cc] && $arrays->{cmpop}->[$cc]) &&
- ($arrays->{cmpconn}->[$cc] eq $conn && $arrays->{cmpop}->[$cc] eq $op)){
- print " - CMP conn=$conn op=$op msgid=$msgid client=$conn_hash->{$conn}\n";
- }
- }
- for (my $mdc = 0; $mdc < $modrdnCount; $mdc++){
- if (($arrays->{modrdnconn}->[$mdc] && $arrays->{modrdnop}->[$mdc]) &&
- ($arrays->{modrdnconn}->[$mdc] eq $conn && $arrays->{modrdnop}->[$mdc] eq $op)){
- print " - MODRDN conn=$conn op=$op msgid=$msgid client=$conn_hash->{$conn}\n";
- }
- }
- for (my $bcb = 0; $bcb < $bindCount; $bcb++){
- if (($arrays->{bindconn}->[$bcb] && $arrays->{bindop}->[$bcb]) &&
- ($arrays->{bindconn}->[$bcb] eq $conn && $arrays->{bindop}->[$bcb] eq $op)){
- print " - BIND conn=$conn op=$op msgid=$msgid client=$conn_hash->{$conn}\n";
- }
- }
- for (my $ubc = 0; $ubc < $unbindCount; $ubc++){
- if (($arrays->{unbindconn}->[$ubc] && $arrays->{unbindop}->[$ubc]) &&
- ($arrays->{unbindconn}->[$ubc] eq $conn && $arrays->{unbindop}->[$ubc] eq $op)){
- print " - UNBIND conn=$conn op=$op msgid=$msgid client=$conn_hash->{$conn}\n";
- }
+ while (my ($conn_op, $targ_msgid) = each %{$abandon_conn_op}) {
+ my ($conn, $op) = split(",", $conn_op);
+ my ($targetop, $msgid) = split(",", $targ_msgid);
+ my $conn_targ = "$conn,$targetop";
+ my $clientIP;
+ if (exists($conn_hash->{$conn}) && defined($conn_hash->{$conn})) {
+ $clientIP = $conn_hash->{$conn};
+ } else {
+ $clientIP = "Unknown";
}
- for (my $ec = 0; $ec < $extopCount; $ec++){
- if (($arrays->{extconn}->[$ec] && $arrays->{extop}->[$ec]) &&
- ($arrays->{extconn}->[$ec] eq $conn && $arrays->{extop}->[$ec] eq $op)){
- print " - EXT conn=$conn op=$op msgid=$msgid client=$conn_hash->{$conn}\n";
- }
+ if (exists($srch_conn_op->{$conn_targ}) && defined($srch_conn_op->{$conn_targ})) {
+ print " - SRCH conn=$conn op=$targetop msgid=$msgid client=$clientIP\n";
+ } elsif (exists($del_conn_op->{$conn_targ}) && defined($del_conn_op->{$conn_targ})) {
+ print " - DEL conn=$conn op=$targetop msgid=$msgid client=$clientIP\n";
+ } elsif (exists($add_conn_op->{$conn_targ}) && defined($add_conn_op->{$conn_targ})) {
+ print " - ADD conn=$conn op=$targetop msgid=$msgid client=$clientIP\n";
+ } elsif (exists($mod_conn_op->{$conn_targ}) && defined($mod_conn_op->{$conn_targ})) {
+ print " - MOD conn=$conn op=$targetop msgid=$msgid client=$clientIP\n";
+ } elsif (exists($cmp_conn_op->{$conn_targ}) && defined($cmp_conn_op->{$conn_targ})) {
+ print " - CMP conn=$conn op=$targetop msgid=$msgid client=$clientIP\n";
+ } elsif (exists($mdn_conn_op->{$conn_targ}) && defined($mdn_conn_op->{$conn_targ})) {
+ print " - MODRDN conn=$conn op=$targetop msgid=$msgid client=$clientIP\n";
+ } elsif (exists($bind_conn_op->{$conn_targ}) && defined($bind_conn_op->{$conn_targ})) {
+ print " - BIND conn=$conn op=$targetop msgid=$msgid client=$clientIP\n";
+ } elsif (exists($unbind_conn_op->{$conn_targ}) && defined($unbind_conn_op->{$conn_targ})) {
+ print " - UNBIND conn=$conn op=$targetop msgid=$msgid client=$clientIP\n";
+ } elsif (exists($ext_conn_op->{$conn_targ}) && defined($ext_conn_op->{$conn_targ})) {
+ print " - EXT conn=$conn op=$targetop msgid=$msgid client=$clientIP\n";
+ } else {
+ print " - UNKNOWN conn=$conn op=$targetop msgid=$msgid client=$clientIP\n";
}
}
}
@@ -1390,8 +1336,8 @@ sub displayUsage {
print "Usage:\n\n";
print " ./logconv.pl [-h] [-d|--rootdn <rootDN>] [-s|--sizeLimit <size limit>] [-v|verison] [-Vi|verbose]\n";
- print " [-S|--startTime <start time>] [-E|--endTime <end time>] \n";
- print " [-efcibaltnxrgjuyp] [ access log ... ... ]\n\n";
+ print " [-S|--startTime <start time>] [-E|--endTime <end time>] \n";
+ print " [-efcibaltnxrgjuyp] [ access log ... ... ]\n\n";
print "- Commandline Switches:\n\n";
@@ -1400,7 +1346,7 @@ sub displayUsage {
print " -D, --data <Location for temporary data files> default is \"/tmp\"\n";
print " -s, --sizeLimit <Number of results to return per catagory> default is 20\n";
print " -X, --excludeIP <IP address to exclude from connection stats> E.g. Load balancers\n";
- print " -v, --version show version of tool\n";
+ print " -v, --version show version of tool\n";
print " -S, --startTime <time to begin analyzing logfile from>\n";
print " E.g. \"[28/Mar/2002:13:14:22 -0800]\"\n";
print " -E, --endTime <time to stop analyzing logfile>\n";
@@ -1450,7 +1396,7 @@ sub displayUsage {
sub
parseLine {
if($reportBinds eq "yes"){
- &parseLineBind();
+ &parseLineBind();
} else {
&parseLineNormal();
}
@@ -1469,26 +1415,26 @@ parseLineBind {
return if $_ =~ /^\s/;
if($firstFile == 1 && $_ =~ /^\[/){
- $start = $_;
- if ($start =~ / *([0-9a-z:\/]+)/i){$start=$1;}
- $firstFile = 0;
+ $start = $_;
+ if ($start =~ / *([0-9a-z:\/]+)/i){$start=$1;}
+ $firstFile = 0;
}
if ($endFlag != 1 && $_ =~ /^\[/ && $_ =~ / *([0-9a-z:\/]+)/i){
$end =$1;
}
if ($startTime && !$startFlag) {
- if (index($_, $startTime) == 0) {
- $startFlag = 1;
- ($start) = $startTime =~ /\D*(\S*)/;
- } else {
- return;
- }
+ if (index($_, $startTime) == 0) {
+ $startFlag = 1;
+ ($start) = $startTime =~ /\D*(\S*)/;
+ } else {
+ return;
+ }
}
if ($endTime && !$endFlag) {
- if (index($_, $endTime) == 0) {
- $endFlag = 1;
- ($end) = $endTime =~ /\D*(\S*)/;
- }
+ if (index($_, $endTime) == 0) {
+ $endFlag = 1;
+ ($end) = $endTime =~ /\D*(\S*)/;
+ }
}
if ($_ =~ /connection from *([0-9A-Fa-f\.\:]+)/i ) {
my $skip = "yes";
@@ -1497,8 +1443,8 @@ parseLineBind {
$skip = "yes";
last;
}
- }
- if ($skip eq "yes"){
+ }
+ if ($skip eq "yes"){
return ;
}
$ip = $1;
@@ -1507,9 +1453,9 @@ parseLineBind {
}
return;
}
- if (/ BIND/ && $_ =~ /dn=\"(.*)\" method/i ){
+ if (/ BIND/ && $_ =~ /dn=\"(.*)\" method/i ){
my $dn;
- if ($1 eq ""){
+ if ($1 eq ""){
$dn = "Anonymous";
} else {
$dn = $1;
@@ -1522,7 +1468,7 @@ parseLineBind {
}
}
$bindReport{$dn}{"binds"}++;
- if ($bindReport{$dn}{"binds"} == 1){
+ if ($bindReport{$dn}{"binds"} == 1){
# For hashes we need to init the counters
$bindReport{$dn}{"srch"} = 0;
$bindReport{$dn}{"add"} = 0;
@@ -1537,7 +1483,7 @@ parseLineBind {
$bindReport{$dn}{"conn"} = $bindReport{$dn}{"conn"} . " $1 ";
}
return;
- }
+ }
if (/ RESULT err=49 /){
processOpForBindReport("failedBind",$logline);
}
@@ -1547,7 +1493,7 @@ parseLineBind {
processOpForBindReport("add",$logline);
} elsif (/ MOD dn=/){
processOpForBindReport("mod",$logline);
- } elsif (/ DEL dn=/){
+ } elsif (/ DEL dn=/){
processOpForBindReport("del",$logline);
} elsif (/ MODRDN dn=/){
processOpForBindReport("modrdn",$logline);
@@ -1555,7 +1501,7 @@ parseLineBind {
processOpForBindReport("cmp",$logline);
} elsif (/ EXT oid=/){
processOpForBindReport("ext",$logline);
- }
+ }
}
sub
@@ -1625,13 +1571,13 @@ sub parseLineNormal
if(!defined($lastzone) or $tzone ne $lastzone)
{
- # tz offset change
- $lastzone=$tzone;
- my ($sign,$hr,$min) = $tzone =~ m/(.)(\d\d)(\d\d)/;
- $tzoff = $hr*3600 + $min*60;
- $tzoff *= -1
- if $sign eq '-';
- # to be subtracted from converted values.
+ # tz offset change
+ $lastzone=$tzone;
+ my ($sign,$hr,$min) = $tzone =~ m/(.)(\d\d)(\d\d)/;
+ $tzoff = $hr*3600 + $min*60;
+ $tzoff *= -1
+ if $sign eq '-';
+ # to be subtracted from converted values.
}
my ($date, $hr, $min, $sec) = split (':', $time);
my ($day, $mon, $yr) = split ('/', $date);
@@ -1641,15 +1587,15 @@ sub parseLineNormal
reset_stats_block( $s_stats, $gmtime, $time.' '.$tzone );
if (!defined($last_min) or $newmin != $last_min)
{
- print_stats_block( $m_stats );
- $time =~ s/\d\d$/00/;
- reset_stats_block( $m_stats, $newmin, $time.' '.$tzone );
- $last_min = $newmin;
+ print_stats_block( $m_stats );
+ $time =~ s/\d\d$/00/;
+ reset_stats_block( $m_stats, $newmin, $time.' '.$tzone );
+ $last_min = $newmin;
}
}
- if (m/ RESULT err/){
- $allResults++;
+ if (m/ RESULT err/){
+ $allResults++;
if($reportStats){ inc_stats('results',$s_stats,$m_stats); }
}
if (m/ SRCH/){
@@ -1666,58 +1612,57 @@ sub parseLineNormal
$anyAttrs++;
}
if ($verb eq "yes"){
- if ($_ =~ /conn= *([0-9A-Z]+)/i){ push @{$arrays->{srchconn}}, $1;}
- if ($_ =~ /op= *([0-9\-]+)/i){ push @{$arrays->{srchop}}, $1;}
+ if ($_ =~ /conn= *([0-9A-Z]+) +op= *([0-9\-]+)/i){ $hashes->{srch_conn_op}->{"$1,$2"}++;}
}
}
if (m/ DEL/){
$delCount++;
if($reportStats){ inc_stats('del',$s_stats,$m_stats); }
if ($verb eq "yes"){
- if ($_ =~ /conn= *([0-9A-Z]+)/i){ push @{$arrays->{delconn}}, $1;}
- if ($_ =~ /op= *([0-9\-]+)/i){ push @{$arrays->{delop}}, $1;}
+ if ($_ =~ /conn= *([0-9A-Z]+) +op= *([0-9\-]+)/i){ $hashes->{del_conn_op}->{"$1,$2"}++;}
}
}
if (m/ MOD dn=/){
$modCount++;
if($reportStats){ inc_stats('mod',$s_stats,$m_stats); }
if ($verb eq "yes"){
- if ($_ =~ /conn= *([0-9A-Z]+)/i){ push @{$arrays->{modconn}}, $1;}
- if ($_ =~ /op= *([0-9\-]+)/i){ push @{$arrays->{modop}}, $1; }
+ if ($_ =~ /conn= *([0-9A-Z]+) +op= *([0-9\-]+)/i){ $hashes->{mod_conn_op}->{"$1,$2"}++;}
}
}
if (m/ ADD/){
$addCount++;
if($reportStats){ inc_stats('add',$s_stats,$m_stats); }
if ($verb eq "yes"){
- if ($_ =~ /conn= *([0-9A-Z]+)/i){ push @{$arrays->{addconn}}, $1; }
- if ($_ =~ /op= *([0-9\-]+)/i){ push @{$arrays->{addop}}, $1; }
+ if ($_ =~ /conn= *([0-9A-Z]+) +op= *([0-9\-]+)/i){ $hashes->{add_conn_op}->{"$1,$2"}++;}
}
}
if (m/ MODRDN/){
$modrdnCount++;
if($reportStats){ inc_stats('modrdn',$s_stats,$m_stats); }
if ($verb eq "yes"){
- if ($_ =~ /conn= *([0-9A-Z]+)/i){ push @{$arrays->{modrdnconn}}, $1; }
- if ($_ =~ /op= *([0-9\-]+)/i){ push @{$arrays->{modrdnop}}, $1; }
+ if ($_ =~ /conn= *([0-9A-Z]+) +op= *([0-9\-]+)/i){ $hashes->{mdn_conn_op}->{"$1,$2"}++;}
}
}
if (m/ CMP dn=/){
$cmpCount++;
if($reportStats){ inc_stats('cmp',$s_stats,$m_stats); }
if ($verb eq "yes" || $usage =~ /g/i){
- if ($_ =~ /conn= *([0-9A-Z]+)/i){ push @{$arrays->{cmpconn}}, $1;}
- if ($_ =~ /op= *([0-9\-]+)/i){ push @{$arrays->{cmpop}}, $1;}
+ if ($_ =~ /conn= *([0-9A-Z]+) +op= *([0-9\-]+)/i){ $hashes->{cmp_conn_op}->{"$1,$2"}++;}
}
}
if (m/ ABANDON /){
+ # there are two cases for abandon
+ # [17/Sep/2013:01:52:11 -0400] conn=1482074 op=4 ABANDON targetop=3 msgid=4
+ # [17/Sep/2013:01:52:11 -0400] conn=1482074 op=4 ABANDON targetop=NOTFOUND msgid=4
+ # if the op to be abandoned completes before the abandon request can be processed
+ # the server will use NOTFOUND as the op number
$abandonCount++;
if($reportStats){ inc_stats('abandon',$s_stats,$m_stats); }
$allResults++;
- if ($_ =~ /targetop= *([0-9a-zA-Z]+)/i ){
- push @{$arrays->{targetop}}, $1;
- if ($_ =~ /conn= *([0-9A-Z]+)/i){ push @{$arrays->{targetconn}}, $1; }
- if ($_ =~ /msgid= *([0-9\-]+)/i){ push @{$arrays->{msgid}}, $1; }
+ if ($_ =~ /conn= *([0-9A-Z]+) +op= *([0-9\-]+) +ABANDON +targetop= *([0-9a-zA-Z]+) +msgid= *([0-9\-]+)/i ){
+ # abandon_conn_op - key is the conn,op of the ABANDON request
+ # the value is the targetop,msgid of the ABANDON request
+ $hashes->{abandon_conn_op}->{"$1,$2"} = "$3,$4"; # targetop,msgid
}
}
if (m/ VLV /){
@@ -1738,11 +1683,11 @@ sub parseLineNormal
$autobindCount++;
$bindCount++;
if($reportStats){ inc_stats('bind',$s_stats,$m_stats); }
- if ($1 ne ""){
+ if ($1 ne ""){
$tmpp = $1;
$tmpp =~ tr/A-Z/a-z/;
$hashes->{bindlist}->{$tmpp}++;
- if($1 eq $rootDN){
+ if($1 eq $rootDN){
$rootDNBindCount++;
}
} else {
@@ -1752,7 +1697,7 @@ sub parseLineNormal
}
}
if (m/ connection from/){
- if ($_ =~ /connection from *([0-9A-Fa-f\.\:]+)/i ){
+ if ($_ =~ /connection from *([0-9A-Fa-f\.\:]+)/i ){
for (my $xxx =0; $xxx < $#excludeIP; $xxx++){
if ($excludeIP[$xxx] eq $1){$exc = "yes";}
}
@@ -1763,7 +1708,7 @@ sub parseLineNormal
}
$simConnection++;
if ($simConnection > $maxsimConnection) {
- $maxsimConnection = $simConnection;
+ $maxsimConnection = $simConnection;
}
($connID) = $_ =~ /conn=(\d*)\s/;
$openConnection[$connID]++;
@@ -1772,7 +1717,7 @@ sub parseLineNormal
my ($date, $hr, $min, $sec) = split (':', $time);
my ($day, $mon, $yr) = split ('/', $date);
$day =~ s/\[//;
- $start_time_of_connection[$connID] = timegm($sec, $min, $hr, $day, $monthname{$mon}, $yr);
+ $hashes->{start_time_of_connection}->{$connID} = timegm($sec, $min, $hr, $day, $monthname{$mon}, $yr);
}
}
if (m/ SSL client bound as /){$sslClientBindCount++;}
@@ -1788,10 +1733,10 @@ sub parseLineNormal
# if we didn't see the start time of this connection
# i.e. due to truncation or log rotation
# then just set to 0
- my $stoc = $start_time_of_connection[$connID] || 0;
- $end_time_of_connection[$connID] = $gmtime || 0;
- my $diff = $end_time_of_connection[$connID] - $stoc;
- $start_time_of_connection[$connID] = $end_time_of_connection[$connID] = 0;
+ my $stoc = $hashes->{start_time_of_connection}->{$connID} || 0;
+ $hashes->{end_time_of_connection}->{$connID} = $gmtime || 0;
+ my $diff = $hashes->{end_time_of_connection}->{$connID} - $stoc;
+ $hashes->{start_time_of_connection}->{$connID} = $hashes->{end_time_of_connection}->{$connID} = 0;
if ($diff <= 1) { $latency[0]++;}
if ($diff == 2) { $latency[1]++;}
if ($diff == 3) { $latency[2]++;}
@@ -1802,85 +1747,82 @@ sub parseLineNormal
}
}
if (m/ BIND/ && $_ =~ /dn=\"(.*)\" method/i ){
+ my $binddn = $1;
if($reportStats){ inc_stats('bind',$s_stats,$m_stats); }
$bindCount++;
- if ($1 ne ""){
- if($1 eq $rootDN){$rootDNBindCount++;}
- $tmpp = $1;
+ my ($conn, $op);
+ if ($_ =~ /conn= *([0-9A-Z]+) +op= *([0-9\-]+)/i){
+ $conn = $1;
+ $op = $2;
+ }
+ if ($binddn ne ""){
+ if($binddn eq $rootDN){$rootDNBindCount++;}
+ $tmpp = $binddn;
$tmpp =~ tr/A-Z/a-z/;
$hashes->{bindlist}->{$tmpp}++;
- if ($_ =~ /conn= *([0-9A-Z]+)/i) { push @{$arrays->{bindconn}}, $1;}
- if ($_ =~ /op= *([0-9\-]+)/i) { push @{$arrays->{bindop}}, $1;}
if($usage =~ /f/ || $verb eq "yes"){
- push @{$arrays->{binddn}}, $tmpp;
+ $hashes->{bind_conn_op}->{"$conn,$op"} = $tmpp;
}
} else {
$anonymousBindCount++;
$hashes->{bindlist}->{"Anonymous Binds"}++;
- if ($_ =~ /conn= *([0-9A-Z]+)/i) { push @{$arrays->{bindconn}}, $1;}
- if ($_ =~ /op= *([0-9\-]+)/i) { push @{$arrays->{bindop}}, $1;}
- push @{$arrays->{binddn}}, "";
+ if($usage =~ /f/ || $verb eq "yes"){
+ $hashes->{bind_conn_op}->{"$conn,$op"} = "";
+ }
inc_stats('anonbind',$s_stats,$m_stats);
}
}
if (m/ UNBIND/){
$unbindCount++;
if ($verb eq "yes"){
- if ($_ =~ /conn= *([0-9A-Z]+)/i){ push @{$arrays->{unbindconn}}, $1; }
- if ($_ =~ /op= *([0-9\-]+)/i){ push @{$arrays->{unbindop}}, $1; }
+ if ($_ =~ /conn= *([0-9A-Z]+) +op= *([0-9\-]+)/i){ $hashes->{unbind_conn_op}->{"$1,$2"}++;}
}
}
- if (m/ RESULT err=/ && m/ notes=P/){
+ if (m/ RESULT err=/ && m/ notes=[A-Z,]*P/){
$pagedSearchCount++;
}
- if (m/ notes=A/){
+ if (m/ notes=[A-Z,]*A/){
$con = "";
if ($_ =~ /conn= *([0-9A-Z]+)/i){
- $con = $1;
- if ($_ =~ /op= *([0-9\-]+)/i){ $op = $1;}
+ $con = $1;
+ if ($_ =~ /op= *([0-9\-]+)/i){ $op = $1;}
}
for (my $i=0; $i < $vlvCount;$i++){
- if ($vlvconn[$i] eq $con && $vlvop[$i] eq $op){ $vlvNotesACount++; $isVlvNotes="1";}
+ if ($vlvconn[$i] eq $con && $vlvop[$i] eq $op){ $vlvNotesACount++; $isVlvNotes="1";}
}
if($isVlvNotes == 0){
# We don't want to record vlv unindexed searches for our regular "bad"
# unindexed search stat, as VLV unindexed searches aren't that bad
$unindexedSrchCountNotesA++;
if($reportStats){ inc_stats('notesA',$s_stats,$m_stats); }
- }
- if ($usage =~ /u/ || $verb eq "yes"){
- if ($isVlvNotes == 0 ){
- if ($_ =~ /etime= *([0-9.]+)/i ){ push @{$arrays->{notesAetime}}, $1; }
- if ($_ =~ /conn= *([0-9A-Z]+)/i){ push @{$arrays->{notesAconn}}, $1; }
- if ($_ =~ /op= *([0-9\-]+)/i){ push @{$arrays->{notesAop}}, $1; }
- if ($_ =~ / *([0-9a-z:\/]+)/i){ push @{$arrays->{notesAtime}}, $1; }
- if ($_ =~ /nentries= *([0-9]+)/i ){ push @{$arrays->{notesAnentries}}, $1; }
+ if ($usage =~ /u/ || $verb eq "yes"){
+ $hashes->{notesa_conn_op}->{"$con,$op"}++;
+ if ($_ =~ /etime= *([0-9.]+)/i ){ $hashes->{etime_conn_op}->{"$con,$op"} = $1; }
+ if ($_ =~ / *([0-9a-z:\/]+)/i){ $hashes->{time_conn_op}->{"$con,$op"} = $1; }
+ if ($_ =~ /nentries= *([0-9]+)/i ){ $hashes->{nentries_conn_op}->{"$con,$op"} = $1; }
}
}
$isVlvNotes = 0;
}
- if (m/ notes=U/){
+ if (m/ notes=[A-Z,]*U/){
$con = "";
if ($_ =~ /conn= *([0-9A-Z]+)/i){
- $con = $1;
- if ($_ =~ /op= *([0-9\-]+)/i){ $op = $1;}
+ $con = $1;
+ if ($_ =~ /op= *([0-9\-]+)/i){ $op = $1;}
}
for (my $i=0; $i < $vlvCount;$i++){
- if ($vlvconn[$i] eq $con && $vlvop[$i] eq $op){ $vlvNotesUCount++; $isVlvNotes="1";}
+ if ($vlvconn[$i] eq $con && $vlvop[$i] eq $op){ $vlvNotesUCount++; $isVlvNotes="1";}
}
if($isVlvNotes == 0){
# We don't want to record vlv unindexed searches for our regular "bad"
# unindexed search stat, as VLV unindexed searches aren't that bad
$unindexedSrchCountNotesU++;
if($reportStats){ inc_stats('notesU',$s_stats,$m_stats); }
- }
- if ($usage =~ /u/ || $verb eq "yes"){
- if ($isVlvNotes == 0 ){
- if ($_ =~ /etime= *([0-9.]+)/i ){ push @{$arrays->{notesUetime}}, $1; }
- if ($_ =~ /conn= *([0-9A-Z]+)/i){ push @{$arrays->{notesUconn}}, $1; }
- if ($_ =~ /op= *([0-9\-]+)/i){ push @{$arrays->{notesUop}}, $1; }
- if ($_ =~ / *([0-9a-z:\/]+)/i){ push @{$arrays->{notesUtime}}, $1; }
- if ($_ =~ /nentries= *([0-9]+)/i ){ push @{$arrays->{notesUnentries}}, $1; }
+ if ($usage =~ /u/ || $verb eq "yes"){
+ $hashes->{notesu_conn_op}->{"$con,$op"}++;
+ if ($_ =~ /etime= *([0-9.]+)/i ){ $hashes->{etime_conn_op}->{"$con,$op"} = $1; }
+ if ($_ =~ / *([0-9a-z:\/]+)/i){ $hashes->{time_conn_op}->{"$con,$op"} = $1; }
+ if ($_ =~ /nentries= *([0-9]+)/i ){ $hashes->{nentries_conn_op}->{"$con,$op"} = $1; }
}
}
$isVlvNotes = 0;
@@ -1941,8 +1883,8 @@ sub parseLineNormal
}
$ip = $1;
$hashes->{ip_hash}->{$ip}++;
- if ($_ =~ /conn= *([0-9A-Z]+)/i ){
- if ($exc ne "yes"){
+ if ($_ =~ /conn= *([0-9A-Z]+)/i ){
+ if ($exc ne "yes"){
$hashes->{conn_hash}->{$1} = $ip;
}
}
@@ -1951,7 +1893,6 @@ sub parseLineNormal
if ($_ =~ /conn= *([0-9A-Z]+)/i) {
$exc = "no";
$ip = getIPfromConn($1);
- if ($ip eq ""){$ip = "Unknown_Host";}
for (my $xxx = 0; $xxx < $#excludeIP; $xxx++){
if ($ip eq $excludeIP[$xxx]){$exc = "yes";}
}
@@ -1966,14 +1907,13 @@ sub parseLineNormal
if ($_ =~ /conn= *([0-9A-Z]+)/i) {
$exc = "no";
$ip = getIPfromConn($1);
- if ($ip eq ""){$ip = "Unknown_Host";}
for (my $xxx = 0; $xxx < $#excludeIP; $xxx++){
- if ($ip eq $excludeIP[$xxx]){$exc = "yes";}
+ if ($ip eq $excludeIP[$xxx]){$exc = "yes";}
}
if ($exc ne "yes"){
$hashes->{B1}->{$ip}++;
$hashes->{conncount}->{"B1"}++;
- $connCodeCount++;
+ $connCodeCount++;
}
}
}
@@ -1981,44 +1921,41 @@ sub parseLineNormal
if ($_ =~ /conn= *([0-9A-Z]+)/i) {
$exc = "no";
$ip = getIPfromConn($1);
- if ($ip eq ""){$ip = "Unknown_Host";}
for (my $xxx = 0; $xxx < $#excludeIP; $xxx++){
- if ($ip eq $excludeIP[$xxx]){$exc = "yes";}
+ if ($ip eq $excludeIP[$xxx]){$exc = "yes";}
}
if ($exc ne "yes"){
$hashes->{B4}->{$ip}++;
$hashes->{conncount}->{"B4"}++;
$connCodeCount++;
}
- }
+ }
}
if (m/- T1/){
if ($_ =~ /conn= *([0-9A-Z]+)/i) {
$exc = "no";
- $ip = getIPfromConn($1);
- if ($ip eq ""){$ip = "Unknown_Host";}
+ $ip = getIPfromConn($1);
for (my $xxx = 0; $xxx < $#excludeIP; $xxx++){
- if ($ip eq $excludeIP[$xxx]){$exc = "yes";}
+ if ($ip eq $excludeIP[$xxx]){$exc = "yes";}
}
if ($exc ne "yes"){
$hashes->{T1}->{$ip}++;
$hashes->{conncount}->{"T1"}++;
- $connCodeCount++;
+ $connCodeCount++;
}
}
}
if (m/- T2/){
if ($_ =~ /conn= *([0-9A-Z]+)/i) {
- $exc = "no";
+ $exc = "no";
$ip = getIPfromConn($1);
- if ($ip eq ""){$ip = "Unknown_Host";}
for (my $xxx = 0; $xxx < $#excludeIP; $xxx++){
- if ($ip eq $excludeIP[$xxx]){$exc = "yes";}
+ if ($ip eq $excludeIP[$xxx]){$exc = "yes";}
}
if ($exc ne "yes"){
$hashes->{T2}->{$ip}++;
$hashes->{conncount}->{"T2"}++;
- $connCodeCount++;
+ $connCodeCount++;
}
}
}
@@ -2027,14 +1964,13 @@ sub parseLineNormal
$exc = "no";
$ip = getIPfromConn($1);
$maxBerSizeCount++;
- if ($ip eq ""){$ip = "Unknown_Host";}
for (my $xxx = 0; $xxx < $#excludeIP; $xxx++){
- if ($ip eq $excludeIP[$xxx]){$exc = "yes";}
+ if ($ip eq $excludeIP[$xxx]){$exc = "yes";}
}
if ($exc ne "yes"){
$hashes->{B2}->{$ip}++;
$hashes->{conncount}->{"B2"}++;
- $connCodeCount++;
+ $connCodeCount++;
}
}
}
@@ -2042,14 +1978,13 @@ sub parseLineNormal
if ($_ =~ /conn= *([0-9A-Z]+)/i) {
$exc = "no";
$ip = getIPfromConn($1);
- if ($ip eq ""){$ip = "Unknown_Host";}
for (my $xxx = 0; $xxx < $#excludeIP; $xxx++){
- if ($ip eq $excludeIP[$xxx]){$exc = "yes";}
+ if ($ip eq $excludeIP[$xxx]){$exc = "yes";}
}
if ($exc ne "yes"){
$hashes->{B3}->{$ip}++;
$hashes->{conncount}->{"B3"}++;
- $connCodeCount++;
+ $connCodeCount++;
}
}
}
@@ -2057,9 +1992,8 @@ sub parseLineNormal
if ($_ =~ /conn= *([0-9A-Z]+)/i) {
$exc = "no";
$ip = getIPfromConn($1);
- if ($ip eq ""){$ip = "Unknown_Host";}
for (my $xxx = 0; $xxx < $#excludeIP; $xxx++){
- if ($ip eq $excludeIP[$xxx]){$exc = "yes";}
+ if ($ip eq $excludeIP[$xxx]){$exc = "yes";}
}
if ($exc ne "yes"){
$hashes->{R1}->{$ip}++;
@@ -2072,14 +2006,13 @@ sub parseLineNormal
if ($_ =~ /conn= *([0-9A-Z]+)/i) {
$exc = "no";
$ip = getIPfromConn($1);
- if ($ip eq ""){$ip = "Unknown_Host";}
for (my $xxx = 0; $xxx < $#excludeIP; $xxx++){
- if ($ip eq $excludeIP[$xxx]){$exc = "yes";}
+ if ($ip eq $excludeIP[$xxx]){$exc = "yes";}
}
if ($exc ne "yes"){
$hashes->{P1}->{$ip}++;
$hashes->{conncount}->{"P1"}++;
- $connCodeCount++;
+ $connCodeCount++;
}
}
}
@@ -2087,9 +2020,8 @@ sub parseLineNormal
if ($_ =~ /conn= *([0-9A-Z]+)/i) {
$exc = "no";
$ip = getIPfromConn($1);
- if ($ip eq ""){$ip = "Unknown_Host";}
for (my $xxx = 0; $xxx < $#excludeIP; $xxx++){
- if ($ip eq $excludeIP[$xxx]){$exc = "yes";}
+ if ($ip eq $excludeIP[$xxx]){$exc = "yes";}
}
if ($exc ne "yes"){
$hashes->{P2}->{$ip}++;
@@ -2102,9 +2034,8 @@ sub parseLineNormal
if ($_ =~ /conn= *([0-9A-Z]+)/i) {
$exc = "no";
$ip = getIPfromConn($1);
- if ($ip eq ""){$ip = "Unknown_Host";}
for (my $xxx = 0; $xxx < $#excludeIP; $xxx++){
- if ($ip eq $excludeIP[$xxx]){$exc = "yes";}
+ if ($ip eq $excludeIP[$xxx]){$exc = "yes";}
}
if ($exc ne "yes"){
$hashes->{U1}->{$ip}++;
@@ -2131,8 +2062,7 @@ sub parseLineNormal
if ($_ =~ /oid=\" *([0-9\.]+)/i ){ $hashes->{oid}->{$1}++; }
if ($1 && $1 eq $startTLSoid){$startTLSCount++;}
if ($verb eq "yes"){
- if ($_ =~ /conn= *([0-9A-Z]+)/i){ push @{$arrays->{extconn}}, $1; }
- if ($_ =~ /op= *([0-9\-]+)/i){ push @{$arrays->{extop}}, $1; }
+ if ($_ =~ /conn= *([0-9A-Z]+) +op= *([0-9\-]+)/i){ $hashes->{ext_conn_op}->{"$1,$2"}++;}
}
}
if (($usage =~ /l/ || $verb eq "yes") and / SRCH /){
@@ -2155,14 +2085,12 @@ sub parseLineNormal
$filterCount++;
if($usage =~ /u/ || $verb eq "yes"){
# we only need this for the unindexed search report
- push @{$arrays->{filterval}}, $tmpp;
- push @{$arrays->{filterconn}}, $filterConn;
- push @{$arrays->{filterop}}, $filterOp;
+ $hashes->{filter_conn_op}->{"$filterConn,$filterOp"} = $tmpp;
}
}
if ($usage =~ /a/ || $verb eq "yes"){
if (/ SRCH / && $_ =~ /base=\"(.*)\" scope/i ){
- my ($baseConn, $baseOp, $scopeVal, $scopeConn, $scopeOp);
+ my ($conn, $op, $scopeVal);
if ($1 eq ""){
$tmpp = "Root DSE";
} else {
@@ -2173,25 +2101,19 @@ sub parseLineNormal
#
# grab the search bases & scope for potential unindexed searches
#
- if ($_ =~ /scope= *([0-9]+)/i) {
- $scopeVal = $1;
+ if ($_ =~ /scope= *([0-9]+)/i) {
+ $scopeVal = $1;
}
- if ($_ =~ /conn= *([0-9A-Z]+)/i) {
- $baseConn = $1;
- $scopeConn = $1;
+ if ($_ =~ /conn= *([0-9A-Z]+)/i) {
+ $conn = $1;
}
- if ($_ =~ /op= *([0-9\-]+)/i) {
- $baseOp = $1;
- $scopeOp = $1;
+ if ($_ =~ /op= *([0-9\-]+)/i) {
+ $op = $1;
}
if($usage =~ /u/ || $verb eq "yes"){
# we only need this for the unindexed search report
- push @{$arrays->{baseval}}, $tmpp;
- push @{$arrays->{baseconn}}, $baseConn;
- push @{$arrays->{baseop}}, $baseOp;
- push @{$arrays->{scopeval}}, $scopeTxt[$scopeVal];
- push @{$arrays->{scopeconn}}, $scopeConn;
- push @{$arrays->{scopeop}}, $scopeOp;
+ $hashes->{base_conn_op}->{"$conn,$op"} = $tmpp;
+ $hashes->{scope_conn_op}->{"$conn,$op"} = $scopeTxt[$scopeVal];
}
$baseCount++;
$scopeCount++;
@@ -2210,15 +2132,8 @@ sub parseLineNormal
$ds6x = "true";
$badPwdCount++;
} elsif (/ err=49 tag=/ ){
- if ($_ =~ /conn= *([0-9A-Z]+)/i ){
- push @{$arrays->{badpwdconn}}, $1;
- $ip = getIPfromConn($1);
- $badPwdCount++;
- }
- if ($_ =~ /op= *([0-9\-]+)/i ){
- push @{$arrays->{badpwdop}}, $1;
- }
- push @{$arrays->{badpwdip}}, $ip;
+ $badPwdCount++;
+ if ($_ =~ /conn= *([0-9A-Z]+) +op= *([0-9\-]+)/i){ $hashes->{badpwd_conn_op}->{"$1,$2"}++;}
}
}
if (/ BIND / && /method=sasl/i){
@@ -2259,29 +2174,17 @@ sub parseLineNormal
sub
reset_stats_block
{
- my $stats = shift;
-
- $stats->{'last'} = shift || 0;
- $stats->{'last_str'} = shift || '';
-
- $stats->{'results'}=0;
- $stats->{'srch'}=0;
- $stats->{'add'}=0;
- $stats->{'mod'}=0;
- $stats->{'modrdn'}=0;
- $stats->{'moddn'}=0;
- $stats->{'cmp'}=0;
- $stats->{'del'}=0;
- $stats->{'abandon'}=0;
- $stats->{'conns'}=0;
- $stats->{'sslconns'}=0;
- $stats->{'bind'}=0;
- $stats->{'anonbind'}=0;
- $stats->{'unbind'}=0;
- $stats->{'notesA'}=0;
- $stats->{'notesU'}=0;
- $stats->{'etime'}=0;
- return;
+ my $stats = shift;
+
+ $stats->{'last'} = shift || 0;
+ $stats->{'last_str'} = shift || '';
+
+ for my $sn (@statnames) {
+ next if ($sn eq 'last' or $sn eq 'last_str');
+ $stats->{$sn}=0;
+ }
+
+ return;
}
sub
@@ -2292,6 +2195,7 @@ new_stats_block
'active' => 0,
};
if ($name){
+ $stats = openHashFiles($dataLocation, @statnames);
$stats->{'filename'} = $name;
$stats->{'fh'} = new IO::File;
$stats->{'active'} = open($stats->{'fh'},">$name");
@@ -2308,32 +2212,32 @@ print_stats_block
if ($stats->{'active'}){
if ($stats->{'last'}){
$stats->{'fh'}->print(
- join(',',
- $stats->{'last_str'},
- $stats->{'last'},
- $stats->{'results'},
- $stats->{'srch'},
- $stats->{'add'},
- $stats->{'mod'},
- $stats->{'modrdn'},
- $stats->{'moddn'},
- $stats->{'cmp'},
- $stats->{'del'},
- $stats->{'abandon'},
- $stats->{'conns'},
- $stats->{'sslconns'},
- $stats->{'bind'},
- $stats->{'anonbind'},
- $stats->{'unbind'},
- $stats->{'notesA'},
- $stats->{'notesU'},
- $stats->{'etime'}),
- "\n" );
+ join(',',
+ $stats->{'last_str'},
+ $stats->{'last'},
+ $stats->{'results'},
+ $stats->{'srch'},
+ $stats->{'add'},
+ $stats->{'mod'},
+ $stats->{'modrdn'},
+ $stats->{'moddn'},
+ $stats->{'cmp'},
+ $stats->{'del'},
+ $stats->{'abandon'},
+ $stats->{'conns'},
+ $stats->{'sslconns'},
+ $stats->{'bind'},
+ $stats->{'anonbind'},
+ $stats->{'unbind'},
+ $stats->{'notesA'},
+ $stats->{'notesU'},
+ $stats->{'etime'}),
+ "\n" );
} else {
$stats->{'fh'}->print(
- "Time,time_t,Results,Search,Add,Mod,Modrdn,Moddn,Compare,Delete,Abandon,".
- "Connections,SSL Conns,Bind,Anon Bind,Unbind,Unindexed search,Unindexed component,ElapsedTime\n"
- );
+ "Time,time_t,Results,Search,Add,Mod,Modrdn,Moddn,Compare,Delete,Abandon,".
+ "Connections,SSL Conns,Bind,Anon Bind,Unbind,Unindexed search,Unindexed component,ElapsedTime\n"
+ );
}
}
}
@@ -2346,7 +2250,7 @@ inc_stats
my $n = shift;
foreach(@_){
$_->{$n}++
- if exists $_->{$n};
+ if exists $_->{$n};
}
return;
}
@@ -2360,7 +2264,7 @@ inc_stats_val
my $val = shift;
foreach(@_){
$_->{$n} += $val
- if exists $_->{$n};
+ if exists $_->{$n};
}
return;
}
@@ -2383,7 +2287,7 @@ displayBindReport
&printClients($bindReport{$bindDN}{"conn"});
print("\n Operations Performed:\n\n");
&printOpStats($bindDN);
- print("\n");
+ print("\n");
}
print "Done.\n";
exit (0);
@@ -2391,13 +2295,13 @@ displayBindReport
sub
printClients
-{
+{
my @bindConns = &cleanConns(split(' ', $_[0]));
my $IPcount = "1";
foreach my $ip ( keys %connList ){ # Loop over all the IP addresses
foreach my $bc (@bindConns){ # Loop over each bind conn number and compare it
- if($connList{$ip} =~ / $bc /){
+ if($connList{$ip} =~ / $bc /){
print(" [$IPcount] $ip\n");
$IPcount++;
last;
@@ -2417,7 +2321,7 @@ cleanConns
if($dirtyConns[$i] ne ""){
$retConns[$c++] = $dirtyConns[$i];
}
- }
+ }
return @retConns;
}
@@ -2443,7 +2347,7 @@ printOpStats
#######################
# #
# Hash File Functions #
-# #
+# #
#######################
sub
@@ -2471,35 +2375,17 @@ openHashFiles
}
sub
-openArrayFiles
-{
- my $dir = shift;
- my %arrays = ();
- for my $an (@_) {
- my @ary = (); # using my in inner loop will create brand new array every time through for tie
- my $fn = "$dir/$an.logconv.db";
- push @removefiles, $fn;
- tie @ary, "DB_File", $fn, O_CREAT|O_RDWR, 0600, $DB_RECNO or do { openFailed($!, $fn) };
- $arrays{$an} = \@ary;
- }
- return \%arrays;
-}
-
-sub
removeDataFiles
{
- if (!$needCleanup) { return ; }
+ if (!$needCleanup) { return ; }
for my $h (keys %{$hashes}) {
untie %{$hashes->{$h}};
}
- for my $a (keys %{$arrays}) {
- untie @{$arrays->{$a}};
- }
for my $file (@removefiles) {
unlink $file;
}
- $needCleanup = 0;
+ $needCleanup = 0;
}
END { print "Cleaning up temp files . . .\n"; removeDataFiles(); print "Done\n"; }
@@ -2508,7 +2394,12 @@ sub
getIPfromConn
{
my $connid = shift;
- return $hashes->{conn_hash}->{$connid};
+ if (exists($hashes->{conn_hash}->{$connid}) &&
+ defined($hashes->{conn_hash}->{$connid})) {
+ return $hashes->{conn_hash}->{$connid};
+ }
+
+ return "Unknown_Host";
}
#######################################
10 years, 6 months
Branch '389-ds-base-1.2.11' - ldap/servers
by Noriko Hosoi
ldap/servers/plugins/replication/cl5_api.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
New commits:
commit f944cd093d05d4bd0784b0c46b91335b6bcebcf2
Author: Thierry bordaz (tbordaz) <tbordaz(a)redhat.com>
Date: Wed Sep 11 11:08:58 2013 +0200
Ticket 47489 - Under specific values of nsDS5ReplicaName, replication may get broken or updates missing
Bug Description:
If the 'nsDS5ReplicaName' (of a replica), contains the database suffix (e.g. 'db', 'db3' or 'db4).
Then replication plugin fails to open the changelog. It could conduct to changelog being recreated or some
last updates to be corrupted.
A consequence that I can reproduce, is that some updates may be removed from the changelog and missing
updates on consumers.
This could conduct to replication break, if for example an entry created is not replicated and then later updated.
Fix Description:
The fix consist to use 'PL_strrstr' rather than 'strstr' to check the database suffix is valid
https://fedorahosted.org/389/ticket/47489
Reviewed by: Rich Megginson (thanks Rich !)
Platforms tested: Fedora 17
Flag Day: no
Doc impact: no
(cherry picked from commit 7a7609d88caf9c0971e694d7eeb78f30aea7fec9)
(cherry picked from commit ac8aad8260d3e5ed403e2d4a9967447a97925ba7)
diff --git a/ldap/servers/plugins/replication/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c
index f17650d..f2e038e 100644
--- a/ldap/servers/plugins/replication/cl5_api.c
+++ b/ldap/servers/plugins/replication/cl5_api.c
@@ -6117,7 +6117,7 @@ static int _cl5FileEndsWith(const char *filename, const char *ext)
{
return 0;
}
- p = strstr(filename, ext);
+ p = PL_strrstr(filename, ext);
if (NULL == p)
{
return 0;
10 years, 6 months
Branch '389-ds-base-1.2.11' - ldap/servers
by Noriko Hosoi
ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c | 39 ++++++++++++++-------------
1 file changed, 21 insertions(+), 18 deletions(-)
New commits:
commit df1f0ed301db6404a8df479a051416da6c8b2738
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Thu Sep 26 09:18:11 2013 -0700
Ticket #47523 - Set up replcation/agreement before initializing the sub suffix, the sub suffix is not found by ldapsearch
Bug description: If a replication is configured against a backend
before initializing the backend with a suffix entry, an RUV entry
is inserted first with the entryid 1. The RUV entry's entryrdn is
added to the entryrdn index with a suffix entry which is a parent
entry of the RUV entry having a temporary entryid 0, which was to
be replaced with the real entryid when the real suffix entry is
added. But the replacement code was not executed.
Fix description: When a real suffix is added to the entryrdn index,
it returns DB_KEYEXIST, which used to be ignored by resetting 0
(== SUCCESS). This patch returns DB_KEYEXIST to the caller and let
_entryrdn_insert_key use the info to replace the temporary entryid
with the real one. The error code is ignored by the other callers.
https://fedorahosted.org/389/ticket/47523
Reviewed by nkinder (Thanks!).
(cherry picked from commit e6eab21920a0374eb356da3d1f041312c6857ecd)
(cherry picked from commit 6b35dc7b04da023cc14045cc6dd1f5e304cf265f)
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
index 156461b..887f74b 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
@@ -747,7 +747,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.data = (void *)newelem;
renamedata.flags = DB_DBT_USERMEM;
rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_SELF, db_txn);
- if (rc) {
+ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"entryrdn_rename_subtree: Adding %s failed; "
"%s(%d)\n", keybuf, dblayer_strerror(rc), rc);
@@ -768,7 +768,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.flags = DB_DBT_USERMEM;
rc = _entryrdn_put_data(cursor, &key,
&renamedata, RDN_INDEX_CHILD, db_txn);
- if (rc) {
+ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */
goto bail;
}
}
@@ -813,7 +813,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.data = (void *)newsupelem;
}
rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_PARENT, db_txn);
- if (rc) {
+ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"entryrdn_rename_subtree: Adding "
"%s failed; %s(%d)\n",
@@ -848,7 +848,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.data = (void *)newelem;
renamedata.flags = DB_DBT_USERMEM;
rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_SELF, db_txn);
- if (rc) {
+ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"entryrdn_rename_subtree: Adding %s failed; "
"%s(%d)\n", keybuf, dblayer_strerror(rc), rc);
@@ -901,7 +901,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.flags = DB_DBT_USERMEM;
}
rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_CHILD, db_txn);
- if (rc) {
+ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */
goto bail;
}
}
@@ -1948,12 +1948,11 @@ _entryrdn_put_data(DBC *cursor, DBT *key, DBT *data, char type, DB_TXN *db_txn)
rc = cursor->c_put(cursor, key, data, DB_NODUPDATA);
if (rc) {
if (DB_KEYEXIST == rc) {
- /* this is okay */
+ /* this is okay, but need to return DB_KEYEXIST to caller */
slapi_log_error(SLAPI_LOG_BACKLDBM, ENTRYRDN_TAG,
"_entryrdn_put_data: The same key (%s) and the "
"data exists in index\n",
(char *)key->data);
- rc = 0;
break;
} else {
char *keyword = NULL;
@@ -2102,7 +2101,7 @@ _entryrdn_insert_key_elems(backend *be,
/* adding RDN to the child key */
rc = _entryrdn_put_data(cursor, key, &adddata, RDN_INDEX_CHILD, db_txn);
keybuf = key->data;
- if (rc) { /* failed */
+ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */
goto bail;
}
@@ -2118,7 +2117,7 @@ _entryrdn_insert_key_elems(backend *be,
key->flags = DB_DBT_USERMEM;
rc = _entryrdn_put_data(cursor, key, &adddata, RDN_INDEX_SELF, db_txn);
- if (rc) { /* failed */
+ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */
goto bail;
}
@@ -2138,6 +2137,9 @@ _entryrdn_insert_key_elems(backend *be,
adddata.flags = DB_DBT_USERMEM;
/* adding RDN to the self key */
rc = _entryrdn_put_data(cursor, key, &adddata, RDN_INDEX_PARENT, db_txn);
+ if (DB_KEYEXIST == rc) { /* failed && ignore already exists */
+ rc = 0;
+ }
/* Succeeded or failed, it's done. */
bail:
slapi_ch_free_string(&keybuf);
@@ -2261,7 +2263,7 @@ _entryrdn_replace_suffix_id(DBC *cursor, DBT *key, DBT *adddata,
/* Add it back */
rc = _entryrdn_put_data(cursor, &realkey, &moddata,
RDN_INDEX_CHILD, db_txn);
- if (rc) {
+ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */
goto bail0;
}
if (curr_childnum + 1 == childnum) {
@@ -2524,7 +2526,7 @@ _entryrdn_insert_key(backend *be,
slapi_ch_free_string(&dn);
goto bail;
}
- elem = _entryrdn_new_rdn_elem(be, 0 /*fake id*/, tmpsrdn, &len);
+ elem = _entryrdn_new_rdn_elem(be, TMPID, tmpsrdn, &len);
if (NULL == elem) {
char *dn = NULL;
slapi_rdn_get_dn(tmpsrdn, &dn);
@@ -2544,12 +2546,13 @@ _entryrdn_insert_key(backend *be,
rc = _entryrdn_get_elem(cursor, &key, &data, nrdn, &elem);
if (rc) {
const char *myrdn = slapi_rdn_get_nrdn(srdn);
- const char *ep = NULL;
+ const char **ep = NULL;
int isexception = 0;
/* Check the RDN is in the exception list */
- for (ep = *rdn_exceptions; ep && *ep; ep++) {
- if (!strcmp(ep, myrdn)) {
+ for (ep = rdn_exceptions; ep && *ep; ep++) {
+ if (!strcmp(*ep, myrdn)) {
isexception = 1;
+ break;
}
}
@@ -2629,7 +2632,7 @@ _entryrdn_insert_key(backend *be,
goto bail;
}
}
- elem = _entryrdn_new_rdn_elem(be, 0 /*fake id*/, tmpsrdn, &len);
+ elem = _entryrdn_new_rdn_elem(be, TMPID, tmpsrdn, &len);
if (NULL == elem) {
char *dn = NULL;
slapi_rdn_get_dn(tmpsrdn, &dn);
@@ -2884,7 +2887,7 @@ _entryrdn_delete_key(backend *be,
slapi_ch_free_string(&dn);
goto bail;
}
- elem = _entryrdn_new_rdn_elem(be, 0 /*fake id*/, tmpsrdn, &len);
+ elem = _entryrdn_new_rdn_elem(be, TMPID, tmpsrdn, &len);
if (NULL == elem) {
char *dn = NULL;
slapi_rdn_get_dn(tmpsrdn, &dn);
@@ -3127,7 +3130,7 @@ _entryrdn_index_read(backend *be,
slapi_ch_free_string(&dn);
goto bail;
}
- *elem = _entryrdn_new_rdn_elem(be, 0 /*fake id*/, tmpsrdn, &len);
+ *elem = _entryrdn_new_rdn_elem(be, TMPID, tmpsrdn, &len);
if (NULL == *elem) {
char *dn = NULL;
slapi_rdn_get_dn(tmpsrdn, &dn);
@@ -3205,7 +3208,7 @@ _entryrdn_index_read(backend *be,
goto bail;
}
}
- tmpelem = _entryrdn_new_rdn_elem(be, 0 /*fake id*/, tmpsrdn, &len);
+ tmpelem = _entryrdn_new_rdn_elem(be, TMPID, tmpsrdn, &len);
if (NULL == tmpelem) {
char *dn = NULL;
slapi_rdn_get_dn(tmpsrdn, &dn);
10 years, 6 months
Branch '389-ds-base-1.3.1' - ldap/servers
by Noriko Hosoi
ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c | 39 ++++++++++++++-------------
1 file changed, 21 insertions(+), 18 deletions(-)
New commits:
commit 6b35dc7b04da023cc14045cc6dd1f5e304cf265f
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Thu Sep 26 09:18:11 2013 -0700
Ticket #47523 - Set up replcation/agreement before initializing the sub suffix, the sub suffix is not found by ldapsearch
Bug description: If a replication is configured against a backend
before initializing the backend with a suffix entry, an RUV entry
is inserted first with the entryid 1. The RUV entry's entryrdn is
added to the entryrdn index with a suffix entry which is a parent
entry of the RUV entry having a temporary entryid 0, which was to
be replaced with the real entryid when the real suffix entry is
added. But the replacement code was not executed.
Fix description: When a real suffix is added to the entryrdn index,
it returns DB_KEYEXIST, which used to be ignored by resetting 0
(== SUCCESS). This patch returns DB_KEYEXIST to the caller and let
_entryrdn_insert_key use the info to replace the temporary entryid
with the real one. The error code is ignored by the other callers.
https://fedorahosted.org/389/ticket/47523
Reviewed by nkinder (Thanks!).
(cherry picked from commit e6eab21920a0374eb356da3d1f041312c6857ecd)
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
index 22940cc..d381166 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
@@ -748,7 +748,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.data = (void *)newelem;
renamedata.flags = DB_DBT_USERMEM;
rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_SELF, db_txn);
- if (rc) {
+ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"entryrdn_rename_subtree: Adding %s failed; "
"%s(%d)\n", keybuf, dblayer_strerror(rc), rc);
@@ -769,7 +769,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.flags = DB_DBT_USERMEM;
rc = _entryrdn_put_data(cursor, &key,
&renamedata, RDN_INDEX_CHILD, db_txn);
- if (rc) {
+ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */
goto bail;
}
}
@@ -814,7 +814,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.data = (void *)newsupelem;
}
rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_PARENT, db_txn);
- if (rc) {
+ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"entryrdn_rename_subtree: Adding "
"%s failed; %s(%d)\n",
@@ -849,7 +849,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.data = (void *)newelem;
renamedata.flags = DB_DBT_USERMEM;
rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_SELF, db_txn);
- if (rc) {
+ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"entryrdn_rename_subtree: Adding %s failed; "
"%s(%d)\n", keybuf, dblayer_strerror(rc), rc);
@@ -902,7 +902,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.flags = DB_DBT_USERMEM;
}
rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_CHILD, db_txn);
- if (rc) {
+ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */
goto bail;
}
}
@@ -1955,12 +1955,11 @@ _entryrdn_put_data(DBC *cursor, DBT *key, DBT *data, char type, DB_TXN *db_txn)
rc = cursor->c_put(cursor, key, data, DB_NODUPDATA);
if (rc) {
if (DB_KEYEXIST == rc) {
- /* this is okay */
+ /* this is okay, but need to return DB_KEYEXIST to caller */
slapi_log_error(SLAPI_LOG_BACKLDBM, ENTRYRDN_TAG,
"_entryrdn_put_data: The same key (%s) and the "
"data exists in index\n",
(char *)key->data);
- rc = 0;
break;
} else {
char *keyword = NULL;
@@ -2109,7 +2108,7 @@ _entryrdn_insert_key_elems(backend *be,
/* adding RDN to the child key */
rc = _entryrdn_put_data(cursor, key, &adddata, RDN_INDEX_CHILD, db_txn);
keybuf = key->data;
- if (rc) { /* failed */
+ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */
goto bail;
}
@@ -2125,7 +2124,7 @@ _entryrdn_insert_key_elems(backend *be,
key->flags = DB_DBT_USERMEM;
rc = _entryrdn_put_data(cursor, key, &adddata, RDN_INDEX_SELF, db_txn);
- if (rc) { /* failed */
+ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */
goto bail;
}
@@ -2145,6 +2144,9 @@ _entryrdn_insert_key_elems(backend *be,
adddata.flags = DB_DBT_USERMEM;
/* adding RDN to the self key */
rc = _entryrdn_put_data(cursor, key, &adddata, RDN_INDEX_PARENT, db_txn);
+ if (DB_KEYEXIST == rc) { /* failed && ignore already exists */
+ rc = 0;
+ }
/* Succeeded or failed, it's done. */
bail:
slapi_ch_free_string(&keybuf);
@@ -2268,7 +2270,7 @@ _entryrdn_replace_suffix_id(DBC *cursor, DBT *key, DBT *adddata,
/* Add it back */
rc = _entryrdn_put_data(cursor, &realkey, &moddata,
RDN_INDEX_CHILD, db_txn);
- if (rc) {
+ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */
goto bail0;
}
if (curr_childnum + 1 == childnum) {
@@ -2531,7 +2533,7 @@ _entryrdn_insert_key(backend *be,
slapi_ch_free_string(&dn);
goto bail;
}
- elem = _entryrdn_new_rdn_elem(be, 0 /*fake id*/, tmpsrdn, &len);
+ elem = _entryrdn_new_rdn_elem(be, TMPID, tmpsrdn, &len);
if (NULL == elem) {
char *dn = NULL;
slapi_rdn_get_dn(tmpsrdn, &dn);
@@ -2551,12 +2553,13 @@ _entryrdn_insert_key(backend *be,
rc = _entryrdn_get_elem(cursor, &key, &data, nrdn, &elem);
if (rc) {
const char *myrdn = slapi_rdn_get_nrdn(srdn);
- const char *ep = NULL;
+ const char **ep = NULL;
int isexception = 0;
/* Check the RDN is in the exception list */
- for (ep = *rdn_exceptions; ep && *ep; ep++) {
- if (!strcmp(ep, myrdn)) {
+ for (ep = rdn_exceptions; ep && *ep; ep++) {
+ if (!strcmp(*ep, myrdn)) {
isexception = 1;
+ break;
}
}
@@ -2636,7 +2639,7 @@ _entryrdn_insert_key(backend *be,
goto bail;
}
}
- elem = _entryrdn_new_rdn_elem(be, 0 /*fake id*/, tmpsrdn, &len);
+ elem = _entryrdn_new_rdn_elem(be, TMPID, tmpsrdn, &len);
if (NULL == elem) {
char *dn = NULL;
slapi_rdn_get_dn(tmpsrdn, &dn);
@@ -2891,7 +2894,7 @@ _entryrdn_delete_key(backend *be,
slapi_ch_free_string(&dn);
goto bail;
}
- elem = _entryrdn_new_rdn_elem(be, 0 /*fake id*/, tmpsrdn, &len);
+ elem = _entryrdn_new_rdn_elem(be, TMPID, tmpsrdn, &len);
if (NULL == elem) {
char *dn = NULL;
slapi_rdn_get_dn(tmpsrdn, &dn);
@@ -3134,7 +3137,7 @@ _entryrdn_index_read(backend *be,
slapi_ch_free_string(&dn);
goto bail;
}
- *elem = _entryrdn_new_rdn_elem(be, 0 /*fake id*/, tmpsrdn, &len);
+ *elem = _entryrdn_new_rdn_elem(be, TMPID, tmpsrdn, &len);
if (NULL == *elem) {
char *dn = NULL;
slapi_rdn_get_dn(tmpsrdn, &dn);
@@ -3212,7 +3215,7 @@ _entryrdn_index_read(backend *be,
goto bail;
}
}
- tmpelem = _entryrdn_new_rdn_elem(be, 0 /*fake id*/, tmpsrdn, &len);
+ tmpelem = _entryrdn_new_rdn_elem(be, TMPID, tmpsrdn, &len);
if (NULL == tmpelem) {
char *dn = NULL;
slapi_rdn_get_dn(tmpsrdn, &dn);
10 years, 6 months
ldap/servers
by Noriko Hosoi
ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c | 39 ++++++++++++++-------------
1 file changed, 21 insertions(+), 18 deletions(-)
New commits:
commit e6eab21920a0374eb356da3d1f041312c6857ecd
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Thu Sep 26 09:18:11 2013 -0700
Ticket #47523 - Set up replcation/agreement before initializing the sub suffix, the sub suffix is not found by ldapsearch
Bug description: If a replication is configured against a backend
before initializing the backend with a suffix entry, an RUV entry
is inserted first with the entryid 1. The RUV entry's entryrdn is
added to the entryrdn index with a suffix entry which is a parent
entry of the RUV entry having a temporary entryid 0, which was to
be replaced with the real entryid when the real suffix entry is
added. But the replacement code was not executed.
Fix description: When a real suffix is added to the entryrdn index,
it returns DB_KEYEXIST, which used to be ignored by resetting 0
(== SUCCESS). This patch returns DB_KEYEXIST to the caller and let
_entryrdn_insert_key use the info to replace the temporary entryid
with the real one. The error code is ignored by the other callers.
https://fedorahosted.org/389/ticket/47523
Reviewed by nkinder (Thanks!).
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
index 22940cc..d381166 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
@@ -748,7 +748,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.data = (void *)newelem;
renamedata.flags = DB_DBT_USERMEM;
rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_SELF, db_txn);
- if (rc) {
+ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"entryrdn_rename_subtree: Adding %s failed; "
"%s(%d)\n", keybuf, dblayer_strerror(rc), rc);
@@ -769,7 +769,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.flags = DB_DBT_USERMEM;
rc = _entryrdn_put_data(cursor, &key,
&renamedata, RDN_INDEX_CHILD, db_txn);
- if (rc) {
+ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */
goto bail;
}
}
@@ -814,7 +814,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.data = (void *)newsupelem;
}
rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_PARENT, db_txn);
- if (rc) {
+ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"entryrdn_rename_subtree: Adding "
"%s failed; %s(%d)\n",
@@ -849,7 +849,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.data = (void *)newelem;
renamedata.flags = DB_DBT_USERMEM;
rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_SELF, db_txn);
- if (rc) {
+ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"entryrdn_rename_subtree: Adding %s failed; "
"%s(%d)\n", keybuf, dblayer_strerror(rc), rc);
@@ -902,7 +902,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.flags = DB_DBT_USERMEM;
}
rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_CHILD, db_txn);
- if (rc) {
+ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */
goto bail;
}
}
@@ -1955,12 +1955,11 @@ _entryrdn_put_data(DBC *cursor, DBT *key, DBT *data, char type, DB_TXN *db_txn)
rc = cursor->c_put(cursor, key, data, DB_NODUPDATA);
if (rc) {
if (DB_KEYEXIST == rc) {
- /* this is okay */
+ /* this is okay, but need to return DB_KEYEXIST to caller */
slapi_log_error(SLAPI_LOG_BACKLDBM, ENTRYRDN_TAG,
"_entryrdn_put_data: The same key (%s) and the "
"data exists in index\n",
(char *)key->data);
- rc = 0;
break;
} else {
char *keyword = NULL;
@@ -2109,7 +2108,7 @@ _entryrdn_insert_key_elems(backend *be,
/* adding RDN to the child key */
rc = _entryrdn_put_data(cursor, key, &adddata, RDN_INDEX_CHILD, db_txn);
keybuf = key->data;
- if (rc) { /* failed */
+ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */
goto bail;
}
@@ -2125,7 +2124,7 @@ _entryrdn_insert_key_elems(backend *be,
key->flags = DB_DBT_USERMEM;
rc = _entryrdn_put_data(cursor, key, &adddata, RDN_INDEX_SELF, db_txn);
- if (rc) { /* failed */
+ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */
goto bail;
}
@@ -2145,6 +2144,9 @@ _entryrdn_insert_key_elems(backend *be,
adddata.flags = DB_DBT_USERMEM;
/* adding RDN to the self key */
rc = _entryrdn_put_data(cursor, key, &adddata, RDN_INDEX_PARENT, db_txn);
+ if (DB_KEYEXIST == rc) { /* failed && ignore already exists */
+ rc = 0;
+ }
/* Succeeded or failed, it's done. */
bail:
slapi_ch_free_string(&keybuf);
@@ -2268,7 +2270,7 @@ _entryrdn_replace_suffix_id(DBC *cursor, DBT *key, DBT *adddata,
/* Add it back */
rc = _entryrdn_put_data(cursor, &realkey, &moddata,
RDN_INDEX_CHILD, db_txn);
- if (rc) {
+ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */
goto bail0;
}
if (curr_childnum + 1 == childnum) {
@@ -2531,7 +2533,7 @@ _entryrdn_insert_key(backend *be,
slapi_ch_free_string(&dn);
goto bail;
}
- elem = _entryrdn_new_rdn_elem(be, 0 /*fake id*/, tmpsrdn, &len);
+ elem = _entryrdn_new_rdn_elem(be, TMPID, tmpsrdn, &len);
if (NULL == elem) {
char *dn = NULL;
slapi_rdn_get_dn(tmpsrdn, &dn);
@@ -2551,12 +2553,13 @@ _entryrdn_insert_key(backend *be,
rc = _entryrdn_get_elem(cursor, &key, &data, nrdn, &elem);
if (rc) {
const char *myrdn = slapi_rdn_get_nrdn(srdn);
- const char *ep = NULL;
+ const char **ep = NULL;
int isexception = 0;
/* Check the RDN is in the exception list */
- for (ep = *rdn_exceptions; ep && *ep; ep++) {
- if (!strcmp(ep, myrdn)) {
+ for (ep = rdn_exceptions; ep && *ep; ep++) {
+ if (!strcmp(*ep, myrdn)) {
isexception = 1;
+ break;
}
}
@@ -2636,7 +2639,7 @@ _entryrdn_insert_key(backend *be,
goto bail;
}
}
- elem = _entryrdn_new_rdn_elem(be, 0 /*fake id*/, tmpsrdn, &len);
+ elem = _entryrdn_new_rdn_elem(be, TMPID, tmpsrdn, &len);
if (NULL == elem) {
char *dn = NULL;
slapi_rdn_get_dn(tmpsrdn, &dn);
@@ -2891,7 +2894,7 @@ _entryrdn_delete_key(backend *be,
slapi_ch_free_string(&dn);
goto bail;
}
- elem = _entryrdn_new_rdn_elem(be, 0 /*fake id*/, tmpsrdn, &len);
+ elem = _entryrdn_new_rdn_elem(be, TMPID, tmpsrdn, &len);
if (NULL == elem) {
char *dn = NULL;
slapi_rdn_get_dn(tmpsrdn, &dn);
@@ -3134,7 +3137,7 @@ _entryrdn_index_read(backend *be,
slapi_ch_free_string(&dn);
goto bail;
}
- *elem = _entryrdn_new_rdn_elem(be, 0 /*fake id*/, tmpsrdn, &len);
+ *elem = _entryrdn_new_rdn_elem(be, TMPID, tmpsrdn, &len);
if (NULL == *elem) {
char *dn = NULL;
slapi_rdn_get_dn(tmpsrdn, &dn);
@@ -3212,7 +3215,7 @@ _entryrdn_index_read(backend *be,
goto bail;
}
}
- tmpelem = _entryrdn_new_rdn_elem(be, 0 /*fake id*/, tmpsrdn, &len);
+ tmpelem = _entryrdn_new_rdn_elem(be, TMPID, tmpsrdn, &len);
if (NULL == tmpelem) {
char *dn = NULL;
slapi_rdn_get_dn(tmpsrdn, &dn);
10 years, 6 months
Branch '389-ds-base-1.3.1' - ldap/servers
by Mark Reynolds
ldap/servers/slapd/util.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
New commits:
commit f7156e0a452af85b5e2604722463ab4e22f3ac0e
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Thu Sep 26 14:42:20 2013 -0400
Ticket 47528 - 389-ds-base built with mozldap can crash from invalid free
Bug Description: The issue is that the slapi_escape_filter_value() returned string gets
freed by the caller. When using mozldap, this function can return the
original filter pointer, which can lead to a double free.
Fix Description: Return a copy of the filter str so it can be safely freed. Also free
the buf if it's not being returned.
https://fedorahosted.org/389/ticket/47528
Reviewed by: nhosoi(Thanks!)
(cherry picked from commit da59cff5e6d27c18bbb02cba98bb99c1bfa37c70)
diff --git a/ldap/servers/slapd/util.c b/ldap/servers/slapd/util.c
index 653914b..0073df5 100644
--- a/ldap/servers/slapd/util.c
+++ b/ldap/servers/slapd/util.c
@@ -477,8 +477,14 @@ slapi_escape_filter_value(char* filter_str, int len)
}
#else
char *buf = slapi_ch_calloc(sizeof(char), filter_len*3+1);
+ char *esc_str = do_escape_string(filter_str, filter_len, buf, special_filter);
- return do_escape_string(filter_str, filter_len, buf, special_filter);
+ if(esc_str != buf){
+ slapi_ch_free_string(&buf);
+ return slapi_ch_strdup(esc_str);
+ } else {
+ return buf;
+ }
#endif
}
10 years, 6 months
ldap/servers
by Mark Reynolds
ldap/servers/slapd/util.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
New commits:
commit da59cff5e6d27c18bbb02cba98bb99c1bfa37c70
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Thu Sep 26 14:42:20 2013 -0400
Ticket 47528 - 389-ds-base built with mozldap can crash from invalid free
Bug Description: The issue is that the slapi_escape_filter_value() returned string gets
freed by the caller. When using mozldap, this function can return the
original filter pointer, which can lead to a double free.
Fix Description: Return a copy of the filter str so it can be safely freed. Also free
the buf if it's not being returned.
https://fedorahosted.org/389/ticket/47528
Reviewed by: nhosoi(Thanks!)
diff --git a/ldap/servers/slapd/util.c b/ldap/servers/slapd/util.c
index 1991040..9dd3822 100644
--- a/ldap/servers/slapd/util.c
+++ b/ldap/servers/slapd/util.c
@@ -477,8 +477,14 @@ slapi_escape_filter_value(char* filter_str, int len)
}
#else
char *buf = slapi_ch_calloc(sizeof(char), filter_len*3+1);
+ char *esc_str = do_escape_string(filter_str, filter_len, buf, special_filter);
- return do_escape_string(filter_str, filter_len, buf, special_filter);
+ if(esc_str != buf){
+ slapi_ch_free_string(&buf);
+ return slapi_ch_strdup(esc_str);
+ } else {
+ return buf;
+ }
#endif
}
10 years, 6 months
Branch '389-ds-base-1.3.0' - ldap/servers
by Richard Allen Megginson
ldap/servers/slapd/back-ldbm/index.c | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
New commits:
commit c96eaa03738e36b7cde0656edfbe6c4769847b52
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Wed Sep 25 08:51:12 2013 -0600
Ticket #47504 idlistscanlimit per index/type/value
https://fedorahosted.org/389/ticket/47504
Reviewed by: nhosoi (Thanks!)
Branch: 389-ds-base-1.3.0
Fix Description: This patch broke replication. The problem is that we cannot
compare the allidslimit to 0 unless the value is explicitly set by
index_get_allids. The fix is to only return ALLIDS if the allidslimit was
explicitly set to 0 by index_get_allids.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
(cherry picked from commit 058d01d7479204a2507dab822cd81e32c37be862)
(cherry picked from commit e5405e627439ccaf370d90c42e65c0a987e33e73)
diff --git a/ldap/servers/slapd/back-ldbm/index.c b/ldap/servers/slapd/back-ldbm/index.c
index f47f63d..66d6e7e 100644
--- a/ldap/servers/slapd/back-ldbm/index.c
+++ b/ldap/servers/slapd/back-ldbm/index.c
@@ -52,7 +52,7 @@
static const char *errmsg = "database index operation failed";
static int is_indexed (const char* indextype, int indexmask, char** index_rules);
-static int index_get_allids( int default_allids, const char *indextype, struct attrinfo *ai, const struct berval *val, unsigned int flags );
+static int index_get_allids( int *allids, const char *indextype, struct attrinfo *ai, const struct berval *val, unsigned int flags );
static Slapi_Value **
valuearray_minus_valuearray(
@@ -985,8 +985,11 @@ index_read_ext_allids(
slapi_pblock_get(pb, SLAPI_SEARCH_IS_AND, &is_and);
}
ai_flags = is_and ? INDEX_ALLIDS_FLAG_AND : 0;
- allidslimit = index_get_allids( allidslimit, indextype, ai, val, ai_flags );
- if (allidslimit == 0) {
+ /* the caller can pass in a value of 0 - just ignore those - but if the index
+ * config sets the allidslimit to 0, this means to skip the index
+ */
+ if (index_get_allids( &allidslimit, indextype, ai, val, ai_flags ) &&
+ (allidslimit == 0)) {
idl = idl_allids( be );
if (unindexed != NULL) *unindexed = 1;
LDAPDebug1Arg( LDAP_DEBUG_BACKLDBM, "<= index_read %lu candidates "
@@ -2410,9 +2413,9 @@ valuearray_minus_valuearray(
#define AI_HAS_TYPE 0x02
#define AI_HAS_FLAG 0x01
static int
-index_get_allids( int default_allids, const char *indextype, struct attrinfo *ai, const struct berval *val, unsigned int flags )
+index_get_allids( int *allids, const char *indextype, struct attrinfo *ai, const struct berval *val, unsigned int flags )
{
- int allids = default_allids;
+ int found = 0;
Slapi_Value sval;
struct index_idlistsizeinfo *iter; /* iterator */
int cookie = 0;
@@ -2420,7 +2423,7 @@ index_get_allids( int default_allids, const char *indextype, struct attrinfo *ai
struct index_idlistsizeinfo *best_match = NULL;
if (!ai->ai_idlistinfo) {
- return allids;
+ return found;
}
if (val) { /* val should already be a Slapi_Value, but some paths do not use Slapi_Value */
@@ -2464,9 +2467,10 @@ index_get_allids( int default_allids, const char *indextype, struct attrinfo *ai
}
if (best_match) {
- allids = best_match->ai_idlistsizelimit;
+ *allids = best_match->ai_idlistsizelimit;
+ found = 1; /* found a match */
}
- return allids;
+ return found;
}
10 years, 6 months