nops.c revision 1.2
1/* $NetBSD: nops.c,v 1.2 2020/08/11 13:15:35 christos 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-2020 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 <sys/cdefs.h> 24__RCSID("$NetBSD: nops.c,v 1.2 2020/08/11 13:15:35 christos Exp $"); 25 26#include "portable.h" 27 28#ifdef SLAPD_OVER_NOPS 29 30#include <stdio.h> 31 32#include <ac/string.h> 33#include <ac/socket.h> 34 35#include "lutil.h" 36#include "slap.h" 37#include "config.h" 38 39static ConfigDriver nops_cf_gen; 40 41static int nops_cf_gen( ConfigArgs *c ) { return 0; } 42 43static void 44nops_rm_mod( Modifications **mods, Modifications *mod ) { 45 Modifications *next, *m; 46 47 next = mod->sml_next; 48 if (*mods == mod) { 49 *mods = next; 50 } else { 51 Modifications *m; 52 53 for (m = *mods; m; m = m->sml_next) { 54 if (m->sml_next == mod) { 55 m->sml_next = next; 56 break; 57 } 58 } 59 } 60 61 mod->sml_next = NULL; 62 slap_mods_free(mod, 1); 63 64 return; 65} 66 67static int 68nops_modify( Operation *op, SlapReply *rs ) 69{ 70 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; 71 Backend *be = op->o_bd; 72 Entry *target_entry = NULL; 73 Modifications *m; 74 int rc; 75 76 if ((m = op->orm_modlist) == NULL) { 77 op->o_bd->bd_info = (BackendInfo *)(on->on_info); 78 send_ldap_error(op, rs, LDAP_INVALID_SYNTAX, 79 "nops() got null orm_modlist"); 80 return(rs->sr_err); 81 } 82 83 op->o_bd = on->on_info->oi_origdb; 84 rc = be_entry_get_rw(op, &op->o_req_ndn, NULL, NULL, 0, &target_entry); 85 op->o_bd = be; 86 87 if (rc != 0 || target_entry == NULL) 88 return 0; 89 90 /* 91 * For each attribute modification, check if the 92 * modification and the old entry are the same. 93 */ 94 while (m) { 95 int i, j; 96 int found; 97 Attribute *a; 98 BerVarray bm; 99 BerVarray bt; 100 Modifications *mc; 101 102 mc = m; 103 m = m->sml_next; 104 105 /* Check only replace sub-operations */ 106 if ((mc->sml_op & LDAP_MOD_OP) != LDAP_MOD_REPLACE) 107 continue; 108 109 /* If there is no values, skip */ 110 if (((bm = mc->sml_values ) == NULL ) || (bm[0].bv_val == NULL)) 111 continue; 112 113 /* If the attribute does not exist in old entry, skip */ 114 if ((a = attr_find(target_entry->e_attrs, mc->sml_desc)) == NULL) 115 continue; 116 if ((bt = a->a_vals) == NULL) 117 continue; 118 119 /* For each value replaced, do we find it in old entry? */ 120 found = 0; 121 for (i = 0; bm[i].bv_val; i++) { 122 for (j = 0; bt[j].bv_val; j++) { 123 if (bm[i].bv_len != bt[j].bv_len) 124 continue; 125 if (memcmp(bm[i].bv_val, bt[j].bv_val, bt[j].bv_len) != 0) 126 continue; 127 128 found++; 129 break; 130 } 131 } 132 133 /* Did we find as many values as we had in old entry? */ 134 if (i != a->a_numvals || found != a->a_numvals) 135 continue; 136 137 /* This is a nop, remove it */ 138 Debug(LDAP_DEBUG_TRACE, "removing nop on %s%s%s", 139 a->a_desc->ad_cname.bv_val, "", ""); 140 141 nops_rm_mod(&op->orm_modlist, mc); 142 } 143 if (target_entry) { 144 op->o_bd = on->on_info->oi_origdb; 145 be_entry_release_r(op, target_entry); 146 op->o_bd = be; 147 } 148 149 if ((m = op->orm_modlist) == NULL) { 150 slap_callback *cb = op->o_callback; 151 152 op->o_bd->bd_info = (BackendInfo *)(on->on_info); 153 op->o_callback = NULL; 154 send_ldap_error(op, rs, LDAP_SUCCESS, ""); 155 op->o_callback = cb; 156 157 return (rs->sr_err); 158 } 159 160 return SLAP_CB_CONTINUE; 161} 162 163static slap_overinst nops_ovl; 164 165#if SLAPD_OVER_NOPS == SLAPD_MOD_DYNAMIC 166static 167#endif 168int 169nops_initialize( void ) { 170 nops_ovl.on_bi.bi_type = "nops"; 171 nops_ovl.on_bi.bi_op_modify = nops_modify; 172 return overlay_register( &nops_ovl ); 173} 174 175#if SLAPD_OVER_NOPS == SLAPD_MOD_DYNAMIC 176int init_module(int argc, char *argv[]) { 177 return nops_initialize(); 178} 179#endif 180 181#endif /* defined(SLAPD_OVER_NOPS) */ 182 183