summaryrefslogtreecommitdiffstats
path: root/contrib/slapd-modules/nops/nops.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/slapd-modules/nops/nops.c')
-rw-r--r--contrib/slapd-modules/nops/nops.c177
1 files changed, 177 insertions, 0 deletions
diff --git a/contrib/slapd-modules/nops/nops.c b/contrib/slapd-modules/nops/nops.c
new file mode 100644
index 0000000..4e8549e
--- /dev/null
+++ b/contrib/slapd-modules/nops/nops.c
@@ -0,0 +1,177 @@
+/* nops.c - Overlay to filter idempotent operations */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2008-2018 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 "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%s%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_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) */
+