1 /* $NetBSD: nops.c,v 1.1.1.4 2014/05/28 09:58:27 tron Exp $ */ 2 3 /* nops.c - Overlay to filter idempotent operations */ 4 /* $OpenLDAP$ */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 2008-2014 The OpenLDAP Foundation. 8 * Copyright 2008 Emmanuel Dreyfus. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted only as authorized by the OpenLDAP 13 * Public License. 14 * 15 * A copy of this license is available in the file LICENSE in the 16 * top-level directory of the distribution or, alternatively, at 17 * <http://www.OpenLDAP.org/license.html>. 18 */ 19 /* ACKNOWLEDGEMENTS: 20 * This work was originally developed by the Emmanuel Dreyfus for 21 * inclusion in OpenLDAP Software. 22 */ 23 #include "portable.h" 24 25 #ifdef SLAPD_OVER_NOPS 26 27 #include <stdio.h> 28 29 #include <ac/string.h> 30 #include <ac/socket.h> 31 32 #include "lutil.h" 33 #include "slap.h" 34 #include "config.h" 35 36 static ConfigDriver nops_cf_gen; 37 38 static int nops_cf_gen( ConfigArgs *c ) { return 0; } 39 40 static void 41 nops_rm_mod( Modifications **mods, Modifications *mod ) { 42 Modifications *next, *m; 43 44 next = mod->sml_next; 45 if (*mods == mod) { 46 *mods = next; 47 } else { 48 Modifications *m; 49 50 for (m = *mods; m; m = m->sml_next) { 51 if (m->sml_next == mod) { 52 m->sml_next = next; 53 break; 54 } 55 } 56 } 57 58 mod->sml_next = NULL; 59 slap_mods_free(mod, 1); 60 61 return; 62 } 63 64 static int 65 nops_modify( Operation *op, SlapReply *rs ) 66 { 67 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; 68 Backend *be = op->o_bd; 69 Entry *target_entry = NULL; 70 Modifications *m; 71 int rc; 72 73 if ((m = op->orm_modlist) == NULL) { 74 op->o_bd->bd_info = (BackendInfo *)(on->on_info); 75 send_ldap_error(op, rs, LDAP_INVALID_SYNTAX, 76 "nops() got null orm_modlist"); 77 return(rs->sr_err); 78 } 79 80 op->o_bd = on->on_info->oi_origdb; 81 rc = be_entry_get_rw(op, &op->o_req_ndn, NULL, NULL, 0, &target_entry); 82 op->o_bd = be; 83 84 if (rc != 0 || target_entry == NULL) 85 return 0; 86 87 /* 88 * For each attribute modification, check if the 89 * modification and the old entry are the same. 90 */ 91 while (m) { 92 int i, j; 93 int found; 94 Attribute *a; 95 BerVarray bm; 96 BerVarray bt; 97 Modifications *mc; 98 99 mc = m; 100 m = m->sml_next; 101 102 /* Check only replace sub-operations */ 103 if ((mc->sml_op & LDAP_MOD_OP) != LDAP_MOD_REPLACE) 104 continue; 105 106 /* If there is no values, skip */ 107 if (((bm = mc->sml_values ) == NULL ) || (bm[0].bv_val == NULL)) 108 continue; 109 110 /* If the attribute does not exist in old entry, skip */ 111 if ((a = attr_find(target_entry->e_attrs, mc->sml_desc)) == NULL) 112 continue; 113 if ((bt = a->a_vals) == NULL) 114 continue; 115 116 /* For each value replaced, do we find it in old entry? */ 117 found = 0; 118 for (i = 0; bm[i].bv_val; i++) { 119 for (j = 0; bt[j].bv_val; j++) { 120 if (bm[i].bv_len != bt[j].bv_len) 121 continue; 122 if (memcmp(bm[i].bv_val, bt[j].bv_val, bt[j].bv_len) != 0) 123 continue; 124 125 found++; 126 break; 127 } 128 } 129 130 /* Did we find as many values as we had in old entry? */ 131 if (i != a->a_numvals || found != a->a_numvals) 132 continue; 133 134 /* This is a nop, remove it */ 135 Debug(LDAP_DEBUG_TRACE, "removing nop on %s%s%s", 136 a->a_desc->ad_cname.bv_val, "", ""); 137 138 nops_rm_mod(&op->orm_modlist, mc); 139 } 140 if (target_entry) { 141 op->o_bd = on->on_info->oi_origdb; 142 be_entry_release_r(op, target_entry); 143 op->o_bd = be; 144 } 145 146 if ((m = op->orm_modlist) == NULL) { 147 slap_callback *cb = op->o_callback; 148 149 op->o_bd->bd_info = (BackendInfo *)(on->on_info); 150 op->o_callback = NULL; 151 send_ldap_error(op, rs, LDAP_SUCCESS, ""); 152 op->o_callback = cb; 153 154 return (rs->sr_err); 155 } 156 157 return SLAP_CB_CONTINUE; 158 } 159 160 static slap_overinst nops_ovl; 161 162 #if SLAPD_OVER_NOPS == SLAPD_MOD_DYNAMIC 163 static 164 #endif 165 int 166 nops_initialize( void ) { 167 nops_ovl.on_bi.bi_type = "nops"; 168 nops_ovl.on_bi.bi_op_modify = nops_modify; 169 return overlay_register( &nops_ovl ); 170 } 171 172 #if SLAPD_OVER_NOPS == SLAPD_MOD_DYNAMIC 173 int init_module(int argc, char *argv[]) { 174 return nops_initialize(); 175 } 176 #endif 177 178 #endif /* defined(SLAPD_OVER_NOPS) */ 179 180