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