Back to index

openldap  2.4.31
nops.c
Go to the documentation of this file.
00001 /* nops.c - Overlay to filter idempotent operations */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 
00004  *
00005  * Copyright 2008-2012 The OpenLDAP Foundation.
00006  * Copyright 2008 Emmanuel Dreyfus.
00007  * All rights reserved.
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted only as authorized by the OpenLDAP
00011  * Public License.
00012  *
00013  * A copy of this license is available in the file LICENSE in the
00014  * top-level directory of the distribution or, alternatively, at
00015  * <http://www.OpenLDAP.org/license.html>.
00016  */
00017 /* ACKNOWLEDGEMENTS:
00018  * This work was originally developed by the Emmanuel Dreyfus for
00019  * inclusion in OpenLDAP Software.
00020  */
00021 #include "portable.h"
00022 
00023 #ifdef SLAPD_OVER_NOPS
00024 
00025 #include <stdio.h>
00026 
00027 #include <ac/string.h>
00028 #include <ac/socket.h>
00029 
00030 #include "lutil.h"
00031 #include "slap.h"
00032 #include "config.h"
00033 
00034 static ConfigDriver nops_cf_gen;
00035 
00036 static int nops_cf_gen( ConfigArgs *c ) { return 0; }
00037 
00038 static void
00039 nops_rm_mod( Modifications **mods, Modifications *mod ) {
00040        Modifications *next, *m;
00041 
00042        next = mod->sml_next;
00043        if (*mods == mod) {
00044               *mods = next;
00045        } else {
00046               Modifications *m;
00047 
00048               for (m = *mods; m; m = m->sml_next) {
00049                      if (m->sml_next == mod) {
00050                             m->sml_next = next;
00051                             break;
00052                      }
00053               }
00054        }
00055 
00056        mod->sml_next = NULL;
00057        slap_mods_free(mod, 1);
00058 
00059        return;
00060 }
00061 
00062 static int
00063 nops_modify( Operation *op, SlapReply *rs )
00064 {
00065        slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
00066        Backend *be = op->o_bd;
00067        Entry *target_entry = NULL;
00068        Modifications *m;
00069        int rc;
00070        
00071        if ((m = op->orm_modlist) == NULL) {
00072               op->o_bd->bd_info = (BackendInfo *)(on->on_info);
00073               send_ldap_error(op, rs, LDAP_INVALID_SYNTAX,
00074                             "nops() got null orm_modlist");
00075               return(rs->sr_err);
00076        }
00077 
00078        op->o_bd = on->on_info->oi_origdb;
00079        rc = be_entry_get_rw(op, &op->o_req_ndn, NULL, NULL, 0,  &target_entry);
00080        op->o_bd = be;
00081 
00082        if (rc != 0 || target_entry == NULL)
00083               return 0;
00084         
00085        /* 
00086         * For each attribute modification, check if the 
00087         * modification and the old entry are the same.
00088         */
00089        while (m) {
00090               int i, j;
00091               int found;
00092               Attribute *a;
00093               BerVarray bm;
00094               BerVarray bt;
00095               Modifications *mc;
00096 
00097               mc = m;
00098               m = m->sml_next;
00099 
00100               /* Check only replace sub-operations */
00101               if ((mc->sml_op & LDAP_MOD_OP) != LDAP_MOD_REPLACE)
00102                      continue;
00103 
00104               /* If there is no values, skip */
00105               if (((bm = mc->sml_values ) == NULL ) || (bm[0].bv_val == NULL))
00106                      continue;
00107 
00108               /* If the attribute does not exist in old entry, skip */
00109               if ((a = attr_find(target_entry->e_attrs, mc->sml_desc)) == NULL)
00110                      continue;
00111               if ((bt = a->a_vals) == NULL)
00112                      continue;
00113 
00114               /* For each value replaced, do we find it in old entry? */
00115               found = 0;
00116               for (i = 0; bm[i].bv_val; i++) {
00117                      for (j = 0; bt[j].bv_val; j++) {
00118                             if (bm[i].bv_len != bt[j].bv_len)
00119                                    continue;
00120                             if (memcmp(bm[i].bv_val, bt[j].bv_val, bt[j].bv_len) != 0)
00121                                    continue;
00122 
00123                             found++;
00124                             break;
00125                      }
00126               }
00127 
00128               /* Did we find as many values as we had in old entry? */
00129               if (i != a->a_numvals || found != a->a_numvals)
00130                      continue;
00131 
00132               /* This is a nop, remove it */
00133               Debug(LDAP_DEBUG_TRACE, "removing nop on %s%s%s",
00134                      a->a_desc->ad_cname.bv_val, "", "");
00135 
00136               nops_rm_mod(&op->orm_modlist, mc);
00137        }
00138        if (target_entry) {
00139               op->o_bd = on->on_info->oi_origdb;
00140               be_entry_release_r(op, target_entry);
00141               op->o_bd = be;
00142        }
00143 
00144        if ((m = op->orm_modlist) == NULL) {
00145               slap_callback *cb = op->o_callback;
00146 
00147               op->o_bd->bd_info = (BackendInfo *)(on->on_info);
00148               op->o_callback = NULL;
00149                 send_ldap_error(op, rs, LDAP_SUCCESS, "");
00150               op->o_callback = cb;
00151 
00152               return (rs->sr_err);
00153        }
00154 
00155        return SLAP_CB_CONTINUE;
00156 }
00157 
00158 static slap_overinst nops_ovl;
00159 
00160 #if SLAPD_OVER_NOPS == SLAPD_MOD_DYNAMIC
00161 static
00162 #endif
00163 int
00164 nops_initialize( void ) {
00165        nops_ovl.on_bi.bi_type = "nops";
00166        nops_ovl.on_bi.bi_op_modify = nops_modify;
00167        return overlay_register( &nops_ovl );
00168 }
00169 
00170 #if SLAPD_OVER_NOPS == SLAPD_MOD_DYNAMIC
00171 int init_module(int argc, char *argv[]) {
00172        return nops_initialize();
00173 }
00174 #endif
00175 
00176 #endif /* defined(SLAPD_OVER_NOPS) */
00177