]> git.sur5r.net Git - openldap/blob - servers/slapd/modify.c
Fix -ULDAP_DEBUG lint.
[openldap] / servers / slapd / modify.c
1 /*
2  * Copyright (c) 1995 Regents of the University of Michigan.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that this notice is preserved and that due credit is given
7  * to the University of Michigan at Ann Arbor. The name of the University
8  * may not be used to endorse or promote products derived from this
9  * software without specific prior written permission. This software
10  * is provided ``as is'' without express or implied warranty.
11  */
12
13 #include "portable.h"
14
15 #include <stdio.h>
16
17 #include <ac/socket.h>
18 #include <ac/string.h>
19 #include <ac/time.h>
20
21 #include "slap.h"
22
23 static void     modlist_free(LDAPModList *ml);
24
25 void
26 do_modify(
27     Connection  *conn,
28     Operation   *op
29 )
30 {
31         char            *ndn;
32         char            *last;
33         unsigned long   tag, len;
34         LDAPModList     *modlist;
35         LDAPModList     **modtail;
36 #ifdef LDAP_DEBUG
37         LDAPModList *tmp;
38 #endif
39         Backend         *be;
40
41         Debug( LDAP_DEBUG_TRACE, "do_modify\n", 0, 0, 0 );
42
43         /*
44          * Parse the modify request.  It looks like this:
45          *
46          *      ModifyRequest := [APPLICATION 6] SEQUENCE {
47          *              name    DistinguishedName,
48          *              mods    SEQUENCE OF SEQUENCE {
49          *                      operation       ENUMERATED {
50          *                              add     (0),
51          *                              delete  (1),
52          *                              replace (2)
53          *                      },
54          *                      modification    SEQUENCE {
55          *                              type    AttributeType,
56          *                              values  SET OF AttributeValue
57          *                      }
58          *              }
59          *      }
60          */
61
62         if ( ber_scanf( op->o_ber, "{a" /*}*/, &ndn ) == LBER_ERROR ) {
63                 Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
64                 send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, "" );
65                 return;
66         }
67
68         Debug( LDAP_DEBUG_ARGS, "do_modify: dn (%s)\n", ndn, 0, 0 );
69
70         (void) dn_normalize_case( ndn );
71
72         /* collect modifications & save for later */
73         modlist = NULL;
74         modtail = &modlist;
75
76         for ( tag = ber_first_element( op->o_ber, &len, &last );
77             tag != LBER_DEFAULT;
78             tag = ber_next_element( op->o_ber, &len, last ) )
79         {
80                 (*modtail) = (LDAPModList *) ch_calloc( 1, sizeof(LDAPModList) );
81
82                 if ( ber_scanf( op->o_ber, "{i{a[V]}}", &(*modtail)->ml_op,
83                     &(*modtail)->ml_type, &(*modtail)->ml_bvalues )
84                     == LBER_ERROR )
85                 {
86                         send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
87                             "decoding error" );
88                         free( ndn );
89                         free( *modtail );
90                         *modtail = NULL;
91                         modlist_free( modlist );
92                         return;
93                 }
94
95                 if ( (*modtail)->ml_op != LDAP_MOD_ADD &&
96                     (*modtail)->ml_op != LDAP_MOD_DELETE &&
97                     (*modtail)->ml_op != LDAP_MOD_REPLACE )
98                 {
99                         send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
100                             "unrecognized modify operation" );
101                         free( ndn );
102                         modlist_free( modlist );
103                         return;
104                 }
105
106                 if ( (*modtail)->ml_bvalues == NULL
107                         && (*modtail)->ml_op != LDAP_MOD_DELETE )
108                 {
109                         send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
110                             "no values given" );
111                         free( ndn );
112                         modlist_free( modlist );
113                         return;
114                 }
115                 attr_normalize( (*modtail)->ml_type );
116
117                 modtail = &(*modtail)->ml_next;
118         }
119         *modtail = NULL;
120
121 #ifdef LDAP_DEBUG
122         Debug( LDAP_DEBUG_ARGS, "modifications:\n", 0, 0, 0 );
123         for ( tmp = modlist; tmp != NULL; tmp = tmp->ml_next ) {
124                 Debug( LDAP_DEBUG_ARGS, "\t%s: %s\n",
125                         tmp->ml_op == LDAP_MOD_ADD
126                                 ? "add" : (tmp->ml_op == LDAP_MOD_DELETE
127                                         ? "delete" : "replace"), tmp->ml_type, 0 );
128         }
129 #endif
130
131         Statslog( LDAP_DEBUG_STATS, "conn=%d op=%d MOD dn=\"%s\"\n",
132             conn->c_connid, op->o_opid, ndn, 0, 0 );
133
134         /*
135          * We could be serving multiple database backends.  Select the
136          * appropriate one, or send a referral to our "referral server"
137          * if we don't hold it.
138          */
139         if ( (be = select_backend( ndn )) == NULL ) {
140                 free( ndn );
141                 modlist_free( modlist );
142                 send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
143                     default_referral );
144                 return;
145         }
146
147         /* alias suffix if approp */
148         ndn = suffixAlias ( ndn, op, be );
149
150         /*
151          * do the modify if 1 && (2 || 3)
152          * 1) there is a modify function implemented in this backend;
153          * 2) this backend is master for what it holds;
154          * 3) it's a replica and the dn supplied is the update_ndn.
155          */
156         if ( be->be_modify ) {
157                 /* do the update here */
158                 if ( be->be_update_ndn == NULL ||
159                         strcmp( be->be_update_ndn, op->o_ndn ) == 0 )
160                 {
161                         if ( (*be->be_modify)( be, conn, op, ndn, modlist ) == 0 ) {
162                                 replog( be, LDAP_REQ_MODIFY, ndn, modlist, 0 );
163                         }
164
165                 /* send a referral */
166                 } else {
167                         send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
168                             default_referral );
169                 }
170         } else {
171                 send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
172                     "Function not implemented" );
173         }
174
175         free( ndn );
176         modlist_free( modlist );
177 }
178
179 static void
180 modlist_free(
181     LDAPModList *ml
182 )
183 {
184         LDAPModList *next;
185
186         for ( ; ml != NULL; ml = next ) {
187                 next = ml->ml_next;
188
189                 free( ml->ml_type );
190                 if ( ml->ml_bvalues != NULL )
191                         ber_bvecfree( ml->ml_bvalues );
192
193                 free( ml );
194         }
195 }