summaryrefslogtreecommitdiffstats
path: root/contrib/slapd-modules/nops
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/slapd-modules/nops')
-rw-r--r--contrib/slapd-modules/nops/Makefile63
-rw-r--r--contrib/slapd-modules/nops/nops.c178
-rw-r--r--contrib/slapd-modules/nops/slapo-nops.532
3 files changed, 273 insertions, 0 deletions
diff --git a/contrib/slapd-modules/nops/Makefile b/contrib/slapd-modules/nops/Makefile
new file mode 100644
index 0000000..1aeb27a
--- /dev/null
+++ b/contrib/slapd-modules/nops/Makefile
@@ -0,0 +1,63 @@
+# $OpenLDAP$
+
+LDAP_SRC = ../../..
+LDAP_BUILD = $(LDAP_SRC)
+LDAP_INC = -I$(LDAP_BUILD)/include -I$(LDAP_SRC)/include -I$(LDAP_SRC)/servers/slapd
+LDAP_LIB = $(LDAP_BUILD)/libraries/libldap/libldap.la \
+ $(LDAP_BUILD)/libraries/liblber/liblber.la
+
+PLAT = UNIX
+NT_LIB = -L$(LDAP_BUILD)/servers/slapd -lslapd
+NT_LDFLAGS = -no-undefined -avoid-version
+UNIX_LDFLAGS = -version-info $(LTVER)
+
+LIBTOOL = $(LDAP_BUILD)/libtool
+INSTALL = /usr/bin/install
+CC = gcc
+OPT = -g -O2
+DEFS = -DSLAPD_OVER_NOPS=SLAPD_MOD_DYNAMIC
+INCS = $(LDAP_INC)
+LIBS = $($(PLAT)_LIB) $(LDAP_LIB)
+LD_FLAGS = $(LDFLAGS) $($(PLAT)_LDFLAGS) -rpath $(moduledir) -module
+
+PROGRAMS = nops.la
+MANPAGES = slapo-nops.5
+LTVER = 0:0:0
+
+prefix=/usr/local
+exec_prefix=$(prefix)
+ldap_subdir=/openldap
+
+libdir=$(exec_prefix)/lib
+libexecdir=$(exec_prefix)/libexec
+moduledir = $(libexecdir)$(ldap_subdir)
+mandir = $(exec_prefix)/share/man
+man5dir = $(mandir)/man5
+
+.SUFFIXES: .c .o .lo
+
+.c.lo:
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) $(OPT) $(CPPFLAGS) $(DEFS) $(INCS) -c $<
+
+all: $(PROGRAMS)
+
+nops.la: nops.lo
+ $(LIBTOOL) --mode=link $(CC) $(LD_FLAGS) -o $@ $? $(LIBS)
+
+clean:
+ rm -rf *.o *.lo *.la .libs
+
+install: install-lib install-man FORCE
+
+install-lib: $(PROGRAMS)
+ mkdir -p $(DESTDIR)$(moduledir)
+ for p in $(PROGRAMS) ; do \
+ $(LIBTOOL) --mode=install cp $$p $(DESTDIR)$(moduledir) ; \
+ done
+
+install-man: $(MANPAGES)
+ mkdir -p $(DESTDIR)$(man5dir)
+ $(INSTALL) -m 644 $(MANPAGES) $(DESTDIR)$(man5dir)
+
+FORCE:
+
diff --git a/contrib/slapd-modules/nops/nops.c b/contrib/slapd-modules/nops/nops.c
new file mode 100644
index 0000000..6dffb6b
--- /dev/null
+++ b/contrib/slapd-modules/nops/nops.c
@@ -0,0 +1,178 @@
+/* nops.c - Overlay to filter idempotent operations */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2008-2022 The OpenLDAP Foundation.
+ * Copyright 2008 Emmanuel Dreyfus.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was originally developed by the Emmanuel Dreyfus for
+ * inclusion in OpenLDAP Software.
+ */
+#include "portable.h"
+
+#ifdef SLAPD_OVER_NOPS
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "lutil.h"
+#include "slap.h"
+#include "slap-config.h"
+
+static ConfigDriver nops_cf_gen;
+
+static int nops_cf_gen( ConfigArgs *c ) { return 0; }
+
+static void
+nops_rm_mod( Modifications **mods, Modifications *mod ) {
+ Modifications *next, *m;
+
+ next = mod->sml_next;
+ if (*mods == mod) {
+ *mods = next;
+ } else {
+ Modifications *m;
+
+ for (m = *mods; m; m = m->sml_next) {
+ if (m->sml_next == mod) {
+ m->sml_next = next;
+ break;
+ }
+ }
+ }
+
+ mod->sml_next = NULL;
+ slap_mods_free(mod, 1);
+
+ return;
+}
+
+static int
+nops_modify( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
+ Backend *be = op->o_bd;
+ Entry *target_entry = NULL;
+ Modifications *m;
+ int rc;
+
+ if ((m = op->orm_modlist) == NULL) {
+ op->o_bd->bd_info = (BackendInfo *)(on->on_info);
+ send_ldap_error(op, rs, LDAP_INVALID_SYNTAX,
+ "nops() got null orm_modlist");
+ return(rs->sr_err);
+ }
+
+ op->o_bd = on->on_info->oi_origdb;
+ rc = be_entry_get_rw(op, &op->o_req_ndn, NULL, NULL, 0, &target_entry);
+ op->o_bd = be;
+
+ if (rc != 0 || target_entry == NULL)
+ return 0;
+
+ /*
+ * For each attribute modification, check if the
+ * modification and the old entry are the same.
+ */
+ while (m) {
+ int i, j;
+ int found;
+ Attribute *a;
+ BerVarray bm;
+ BerVarray bt;
+ Modifications *mc;
+
+ mc = m;
+ m = m->sml_next;
+
+ /* Check only replace sub-operations */
+ if ((mc->sml_op & LDAP_MOD_OP) != LDAP_MOD_REPLACE)
+ continue;
+
+ /* If there is no values, skip */
+ if (((bm = mc->sml_values ) == NULL ) || (bm[0].bv_val == NULL))
+ continue;
+
+ /* If the attribute does not exist in old entry, skip */
+ if ((a = attr_find(target_entry->e_attrs, mc->sml_desc)) == NULL)
+ continue;
+ if ((bt = a->a_vals) == NULL)
+ continue;
+
+ /* For each value replaced, do we find it in old entry? */
+ found = 0;
+ for (i = 0; bm[i].bv_val; i++) {
+ for (j = 0; bt[j].bv_val; j++) {
+ if (bm[i].bv_len != bt[j].bv_len)
+ continue;
+ if (memcmp(bm[i].bv_val, bt[j].bv_val, bt[j].bv_len) != 0)
+ continue;
+
+ found++;
+ break;
+ }
+ }
+
+ /* Did we find as many values as we had in old entry? */
+ if (i != a->a_numvals || found != a->a_numvals)
+ continue;
+
+ /* This is a nop, remove it */
+ Debug(LDAP_DEBUG_TRACE, "removing nop on %s",
+ a->a_desc->ad_cname.bv_val );
+
+ nops_rm_mod(&op->orm_modlist, mc);
+ }
+ if (target_entry) {
+ op->o_bd = on->on_info->oi_origdb;
+ be_entry_release_r(op, target_entry);
+ op->o_bd = be;
+ }
+
+ if ((m = op->orm_modlist) == NULL) {
+ slap_callback *cb = op->o_callback;
+
+ op->o_bd->bd_info = (BackendInfo *)(on->on_info);
+ op->o_callback = NULL;
+ send_ldap_error(op, rs, LDAP_SUCCESS, "");
+ op->o_callback = cb;
+
+ return (rs->sr_err);
+ }
+
+ return SLAP_CB_CONTINUE;
+}
+
+static slap_overinst nops_ovl;
+
+#if SLAPD_OVER_NOPS == SLAPD_MOD_DYNAMIC
+static
+#endif
+int
+nops_initialize( void ) {
+ nops_ovl.on_bi.bi_type = "nops";
+ nops_ovl.on_bi.bi_flags = SLAPO_BFLAG_SINGLE;
+ nops_ovl.on_bi.bi_op_modify = nops_modify;
+ return overlay_register( &nops_ovl );
+}
+
+#if SLAPD_OVER_NOPS == SLAPD_MOD_DYNAMIC
+int init_module(int argc, char *argv[]) {
+ return nops_initialize();
+}
+#endif
+
+#endif /* defined(SLAPD_OVER_NOPS) */
+
diff --git a/contrib/slapd-modules/nops/slapo-nops.5 b/contrib/slapd-modules/nops/slapo-nops.5
new file mode 100644
index 0000000..c27915e
--- /dev/null
+++ b/contrib/slapd-modules/nops/slapo-nops.5
@@ -0,0 +1,32 @@
+.TH SLAPO-NOPS 5 "RELEASEDATE" "OpenLDAP LDVERSION"
+.\" Copyright 2008 Emmanuel Dreyfus
+.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
+.\" $OpenLDAP$
+.SH NAME
+slapo-nops \- Remove Null Operations Overlay to slapd
+.SH SYNOPSIS
+ETCDIR/slapd.conf
+.SH DESCRIPTION
+Some broken client tend to implement modifications as replace operations
+where all attributes are replaced, most of the time by the same values
+they had before. This can cause undesirable load on logs, ACL evaluation,
+or replication traffic.
+
+This overlay detects idempotent replace operations and filter them out.
+.SH CONFIGURATION
+This overlay had no specific configuration.
+.SH EXAMPLES
+.LP
+.RS
+.nf
+overlay nops
+.RE
+.SH FILES
+.TP
+ETCDIR/slapd.conf
+default slapd configuration file
+.SH SEE ALSO
+.BR slapd.conf (5).
+.SH ACKNOWLEDGEMENTS
+This module was written in 2008 by Emmanuel Dreyfus.
+.so ../Project