]> git.sur5r.net Git - openldap/blob - servers/slapd/back-meta/delete.c
dd105b0756c1ae1e77617b1f5e0e6acf842dfb5a
[openldap] / servers / slapd / back-meta / delete.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1999-2006 The OpenLDAP Foundation.
5  * Portions Copyright 2001-2003 Pierangelo Masarati.
6  * Portions Copyright 1999-2003 Howard Chu.
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 initially developed by the Howard Chu for inclusion
19  * in OpenLDAP Software and subsequently enhanced by Pierangelo
20  * Masarati.
21  */
22
23 #include "portable.h"
24
25 #include <stdio.h>
26
27 #include <ac/string.h>
28 #include <ac/socket.h>
29
30 #include "slap.h"
31 #include "../back-ldap/back-ldap.h"
32 #include "back-meta.h"
33
34 int
35 meta_back_delete( Operation *op, SlapReply *rs )
36 {
37         metainfo_t      *mi = ( metainfo_t * )op->o_bd->be_private;
38         metatarget_t    *mt;
39         metaconn_t      *mc = NULL;
40         int             candidate = -1;
41         struct berval   mdn = BER_BVNULL;
42         dncookie        dc;
43         int             msgid;
44         int             do_retry = 1;
45         int             maperr = 1;
46         LDAPControl     **ctrls = NULL;
47
48         mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
49         if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR ) ) {
50                 return rs->sr_err;
51         }
52
53         assert( mc->mc_conns[ candidate ].msc_ld != NULL );
54
55         /*
56          * Rewrite the compare dn, if needed
57          */
58         mt = mi->mi_targets[ candidate ];
59         dc.target = mt;
60         dc.conn = op->o_conn;
61         dc.rs = rs;
62         dc.ctx = "deleteDN";
63
64         if ( ldap_back_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
65                 send_ldap_result( op, rs );
66                 goto done;
67         }
68
69         ctrls = op->o_ctrls;
70         if ( ldap_back_proxy_authz_ctrl( &mc->mc_conns[ candidate ].msc_bound_ndn,
71                 mt->mt_version, &mt->mt_idassert, op, rs, &ctrls ) != LDAP_SUCCESS )
72         {
73                 maperr = 0;
74                 goto sendres;
75         }
76
77 retry:;
78         rs->sr_err = ldap_delete_ext( mc->mc_conns[ candidate ].msc_ld,
79                         mdn.bv_val, ctrls, NULL, &msgid );
80         if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
81                 do_retry = 0;
82                 if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
83                         goto retry;
84                 }
85                 goto cleanup;
86
87         } else if ( rs->sr_err == LDAP_SUCCESS ) {
88                 struct timeval  tv, *tvp = NULL;
89                 LDAPMessage     *res = NULL;
90                 int             rc;
91
92                 if ( mt->mt_timeout[ LDAP_BACK_OP_DELETE ] != 0 ) {
93                         tv.tv_sec = mt->mt_timeout[ LDAP_BACK_OP_DELETE ];
94                         tv.tv_usec = 0;
95                         tvp = &tv;
96                 }
97
98                 rs->sr_err = LDAP_OTHER;
99                 maperr = 0;
100                 rc = ldap_result( mc->mc_conns[ candidate ].msc_ld,
101                         msgid, LDAP_MSG_ALL, tvp, &res );
102                 switch ( rc ) {
103                 case -1:
104                         rs->sr_err = LDAP_OTHER;
105                         break;
106
107                 case 0:
108                         (void)meta_back_cancel( mc, op, rs, msgid, candidate, LDAP_BACK_DONTSEND );
109                         rs->sr_err = op->o_protocol >= LDAP_VERSION3 ?
110                                 LDAP_ADMINLIMIT_EXCEEDED : LDAP_OPERATIONS_ERROR;
111                         break;
112
113                 case LDAP_RES_DELETE:
114                         /* FIXME: matched? referrals? response controls? */
115                         rc = ldap_parse_result( mc->mc_conns[ candidate ].msc_ld,
116                                 res, &rs->sr_err, NULL, NULL, NULL, NULL, 1 );
117                         if ( rc != LDAP_SUCCESS ) {
118                                 rs->sr_err = rc;
119                         }
120                         maperr = 1;
121                         break;
122
123                 default:
124                         ldap_msgfree( res );
125                         break;
126                 }
127         }
128
129 sendres:;
130         (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
131
132         if ( maperr ) {
133                 rs->sr_err = meta_back_op_result( mc, op, rs, candidate );
134
135         } else {
136                 send_ldap_result( op, rs );
137
138                 if ( META_BACK_TGT_QUARANTINE( mt ) ) {
139                         meta_back_quarantine( op, rs, candidate );
140                 }
141         }
142
143 cleanup:;
144         if ( mdn.bv_val != op->o_req_dn.bv_val ) {
145                 free( mdn.bv_val );
146                 BER_BVZERO( &mdn );
147         }
148         
149 done:;
150         if ( mc ) {
151                 meta_back_release_conn( op, mc );
152         }
153
154         return rs->sr_err;
155 }
156