]> git.sur5r.net Git - openldap/blob - servers/slapd/back-asyncmeta/compare.c
Happy New Year
[openldap] / servers / slapd / back-asyncmeta / compare.c
1 /* compare.c - compare exop handler for back-asyncmeta */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2016-2018 The OpenLDAP Foundation.
6  * Portions Copyright 2016 Symas Corporation.
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
18 /* ACKNOWLEDGEMENTS:
19 + * This work was developed by Symas Corporation
20 + * based on back-meta module for inclusion in OpenLDAP Software.
21 + * This work was sponsored by Ericsson. */
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-asyncmeta.h"
33 #include "../../../libraries/liblber/lber-int.h"
34 #include "../../../libraries/libldap/ldap-int.h"
35
36 meta_search_candidate_t
37 asyncmeta_back_compare_start(Operation *op,
38                             SlapReply *rs,
39                             a_metaconn_t *mc,
40                             bm_context_t *bc,
41                             int candidate)
42 {
43         a_dncookie      dc;
44         a_metainfo_t    *mi = mc->mc_info;
45         a_metatarget_t  *mt = mi->mi_targets[ candidate ];
46         struct berval   mdn = BER_BVNULL;
47         struct berval   mapped_attr = op->orc_ava->aa_desc->ad_cname;
48         struct berval   mapped_value = op->orc_ava->aa_value;
49         int rc = 0, nretries = 1;
50         LDAPControl     **ctrls = NULL;
51         meta_search_candidate_t retcode = META_SEARCH_CANDIDATE;
52         BerElement *ber = NULL;
53         a_metasingleconn_t      *msc = &mc->mc_conns[ candidate ];
54         SlapReply               *candidates = bc->candidates;
55         ber_int_t       msgid;
56
57         dc.target = mt;
58         dc.conn = op->o_conn;
59         dc.rs = rs;
60         dc.ctx = "compareDN";
61
62         switch ( asyncmeta_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
63         case LDAP_UNWILLING_TO_PERFORM:
64                 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
65                 retcode = META_SEARCH_ERR;
66                 goto doreturn;
67         default:
68                 break;
69         }
70
71         /*
72          * if attr is objectClass, try to remap the value
73          */
74         if ( op->orc_ava->aa_desc == slap_schema.si_ad_objectClass ) {
75                 asyncmeta_map( &mt->mt_rwmap.rwm_oc,
76                                 &op->orc_ava->aa_value,
77                                 &mapped_value, BACKLDAP_MAP );
78
79                 if ( BER_BVISNULL( &mapped_value ) || BER_BVISEMPTY( &mapped_value ) ) {
80                         rs->sr_err = LDAP_OTHER;
81                         retcode = META_SEARCH_ERR;
82                         goto done;
83                 }
84
85         /*
86          * else try to remap the attribute
87          */
88         } else {
89                 asyncmeta_map( &mt->mt_rwmap.rwm_at,
90                         &op->orc_ava->aa_desc->ad_cname,
91                         &mapped_attr, BACKLDAP_MAP );
92                 if ( BER_BVISNULL( &mapped_attr ) || BER_BVISEMPTY( &mapped_attr ) ) {
93                         rs->sr_err = LDAP_OTHER;
94                         retcode = META_SEARCH_ERR;
95                         goto done;
96                 }
97
98                 if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
99                 {
100                         dc.ctx = "compareAttrDN";
101
102                         switch ( asyncmeta_dn_massage( &dc, &op->orc_ava->aa_value, &mapped_value ) )
103                         {
104                         case LDAP_UNWILLING_TO_PERFORM:
105                                 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
106                                 retcode = META_SEARCH_ERR;
107                                 goto done;
108
109                         default:
110                                 break;
111                         }
112                 }
113         }
114 retry:;
115         ctrls = op->o_ctrls;
116         if ( asyncmeta_controls_add( op, rs, mc, candidate, &ctrls ) != LDAP_SUCCESS )
117         {
118                 candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
119                 retcode = META_SEARCH_ERR;
120                 goto done;
121         }
122
123         ber = ldap_build_compare_req( msc->msc_ld, mdn.bv_val, mapped_attr.bv_val, &mapped_value,
124                         ctrls, NULL, &msgid);
125         if (ber) {
126                 candidates[ candidate ].sr_msgid = msgid;
127                 rc = ldap_send_initial_request( msc->msc_ld, LDAP_REQ_COMPARE,
128                                                 mdn.bv_val, ber, msgid );
129                 if (rc == msgid)
130                         rc = LDAP_SUCCESS;
131                 else
132                         rc = LDAP_SERVER_DOWN;
133
134                 switch ( rc ) {
135                 case LDAP_SUCCESS:
136                         retcode = META_SEARCH_CANDIDATE;
137                         asyncmeta_set_msc_time(msc);
138                         break;
139
140                 case LDAP_SERVER_DOWN:
141                         ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
142                         asyncmeta_clear_one_msc(NULL, mc, candidate);
143                         ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
144                         if ( nretries && asyncmeta_retry( op, rs, &mc, candidate, LDAP_BACK_DONTSEND ) ) {
145                                 nretries = 0;
146                                 /* if the identity changed, there might be need to re-authz */
147                                 (void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
148                                 goto retry;
149                         }
150
151                 default:
152                         candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
153                         retcode = META_SEARCH_ERR;
154                 }
155         }
156 done:
157         (void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
158
159         if ( mdn.bv_val != op->o_req_dn.bv_val ) {
160                 free( mdn.bv_val );
161         }
162
163         if ( op->orc_ava->aa_value.bv_val != mapped_value.bv_val ) {
164                 free( mapped_value.bv_val );
165         }
166
167 doreturn:;
168         Debug( LDAP_DEBUG_TRACE, "%s <<< asyncmeta_back_compare_start[%p]=%d\n", op->o_log_prefix, msc, candidates[candidate].sr_msgid );
169         return retcode;
170 }
171
172 int
173 asyncmeta_back_compare( Operation *op, SlapReply *rs )
174 {
175         a_metainfo_t    *mi = ( a_metainfo_t * )op->o_bd->be_private;
176         a_metatarget_t  *mt;
177         a_metaconn_t    *mc;
178         int             rc, candidate = -1;
179         OperationBuffer opbuf;
180         bm_context_t *bc;
181         SlapReply *candidates;
182         slap_callback *cb = op->o_callback;
183
184         Debug(LDAP_DEBUG_ARGS, "==> asyncmeta_back_compare: %s\n",
185               op->o_req_dn.bv_val, 0, 0 );
186
187         asyncmeta_new_bm_context(op, rs, &bc, mi->mi_ntargets );
188         if (bc == NULL) {
189                 rs->sr_err = LDAP_OTHER;
190                 asyncmeta_sender_error(op, rs, cb);
191                 return rs->sr_err;
192         }
193
194         candidates = bc->candidates;
195         mc = asyncmeta_getconn( op, rs, candidates, &candidate, LDAP_BACK_DONTSEND, 0);
196         if ( !mc || rs->sr_err != LDAP_SUCCESS) {
197                 asyncmeta_sender_error(op, rs, cb);
198                 asyncmeta_clear_bm_context(bc);
199                 return rs->sr_err;
200         }
201
202         mt = mi->mi_targets[ candidate ];
203         bc->timeout = mt->mt_timeout[ SLAP_OP_COMPARE ];
204         bc->retrying = LDAP_BACK_RETRYING;
205         bc->sendok = ( LDAP_BACK_SENDRESULT | bc->retrying );
206         bc->stoptime = op->o_time + bc->timeout;
207
208         ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
209         rc = asyncmeta_add_message_queue(mc, bc);
210         ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
211
212         if (rc != LDAP_SUCCESS) {
213                 rs->sr_err = LDAP_BUSY;
214                 rs->sr_text = "Maximum pending ops limit exceeded";
215                 asyncmeta_clear_bm_context(bc);
216                 asyncmeta_sender_error(op, rs, cb);
217                 goto finish;
218         }
219
220         rc = asyncmeta_dobind_init_with_retry(op, rs, bc, mc, candidate);
221         switch (rc)
222         {
223         case META_SEARCH_CANDIDATE:
224                 /* target is already bound, just send the request */
225                 Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_compare:  "
226                        "cnd=\"%ld\"\n", op->o_log_prefix, candidate , 0);
227
228                 rc = asyncmeta_back_compare_start( op, rs, mc, bc, candidate);
229                 if (rc == META_SEARCH_ERR) {
230                         ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
231                         asyncmeta_drop_bc(mc, bc);
232                         ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
233                         asyncmeta_sender_error(op, rs, cb);
234                         asyncmeta_clear_bm_context(bc);
235                         goto finish;
236
237                 }
238                         break;
239         case META_SEARCH_NOT_CANDIDATE:
240                 Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_compare: NOT_CANDIDATE "
241                        "cnd=\"%ld\"\n", op->o_log_prefix, candidate , 0);
242                 candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
243                 ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
244                 asyncmeta_drop_bc(mc, bc);
245                 ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
246                 asyncmeta_sender_error(op, rs, cb);
247                 asyncmeta_clear_bm_context(bc);
248                 goto finish;
249
250         case META_SEARCH_NEED_BIND:
251         case META_SEARCH_CONNECTING:
252                 Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_compare: NEED_BIND "
253                        "cnd=\"%ld\" %p\n", op->o_log_prefix, candidate , &mc->mc_conns[candidate]);
254                 rc = asyncmeta_dobind_init(op, rs, bc, mc, candidate);
255                 if (rc == META_SEARCH_ERR) {
256                         ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
257                         asyncmeta_drop_bc(mc, bc);
258                         ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
259                         asyncmeta_sender_error(op, rs, cb);
260                         asyncmeta_clear_bm_context(bc);
261                         goto finish;
262                 }
263                 break;
264         case META_SEARCH_BINDING:
265                         Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_compare: BINDING "
266                                "cnd=\"%ld\" %p\n", op->o_log_prefix, candidate , &mc->mc_conns[candidate]);
267                         /* Todo add the context to the message queue but do not send the request
268                            the receiver must send this when we are done binding */
269                         /* question - how would do receiver know to which targets??? */
270                         break;
271
272         case META_SEARCH_ERR:
273                         Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_compare: ERR "
274                                "cnd=\"%ldd\"\n", op->o_log_prefix, candidate , 0);
275                         candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
276                         candidates[ candidate ].sr_type = REP_RESULT;
277                         ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
278                         asyncmeta_drop_bc(mc, bc);
279                         ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
280                         asyncmeta_sender_error(op, rs, cb);
281                         asyncmeta_clear_bm_context(bc);
282                         goto finish;
283                 default:
284                         assert( 0 );
285                         break;
286                 }
287         ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
288         asyncmeta_start_one_listener(mc, candidates, bc, candidate);
289         ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
290 finish:
291         return rs->sr_err;
292
293 }