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