diff options
Diffstat (limited to 'contrib/slapd-modules/nops')
-rw-r--r-- | contrib/slapd-modules/nops/Makefile | 58 | ||||
-rw-r--r-- | contrib/slapd-modules/nops/nops.c | 178 | ||||
-rw-r--r-- | contrib/slapd-modules/nops/slapo-nops.5 | 32 |
3 files changed, 268 insertions, 0 deletions
diff --git a/contrib/slapd-modules/nops/Makefile b/contrib/slapd-modules/nops/Makefile new file mode 100644 index 0000000..94a5bcd --- /dev/null +++ b/contrib/slapd-modules/nops/Makefile @@ -0,0 +1,58 @@ +# $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 + +LIBTOOL = $(LDAP_BUILD)/libtool +INSTALL = /usr/bin/install +CC = gcc +OPT = -g -O2 +DEFS = -DSLAPD_OVER_NOPS=SLAPD_MOD_DYNAMIC +INCS = $(LDAP_INC) +LIBS = $(LDAP_LIB) + +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) $(LDFLAGS) -version-info $(LTVER) \ + -rpath $(moduledir) -module -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 |