1 /*	$NetBSD: back-asyncmeta.h,v 1.2 2021/08/14 16:14:59 christos Exp $	*/
2 
3 /* back-asyncmeta.h - main header file for back-asyncmeta module */
4 /* $OpenLDAP$ */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 2016-2021 The OpenLDAP Foundation.
8  * Portions Copyright 2016 Symas Corporation.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted only as authorized by the OpenLDAP
13  * Public License.
14  *
15  * A copy of this license is available in the file LICENSE in the
16  * top-level directory of the distribution or, alternatively, at
17  * <http://www.OpenLDAP.org/license.html>.
18  */
19 
20 /* ACKNOWLEDGEMENTS:
21  * This work was developed by Symas Corporation
22  * based on back-meta module for inclusion in OpenLDAP Software.
23  * This work was sponsored by Ericsson. */
24 
25 #ifndef SLAPD_LDAP_H
26 #error "include servers/slapd/back-ldap/back-ldap.h before this file!"
27 #endif /* SLAPD_LDAP_H */
28 
29 #ifndef SLAPD_ASYNCMETA_H
30 #define SLAPD_ASYNCMETA_H
31 
32 #ifdef LDAP_DEVEL
33 #define SLAPD_META_CLIENT_PR 1
34 #endif /* LDAP_DEVEL */
35 
36 #include "proto-asyncmeta.h"
37 
38 #include "ldap_rq.h"
39 
40 LDAP_BEGIN_DECL
41 
42 /*
43  * Set META_BACK_PRINT_CONNTREE larger than 0 to dump the connection tree (debug only)
44  */
45 #ifndef META_BACK_PRINT_CONNTREE
46 #define META_BACK_PRINT_CONNTREE 0
47 #endif /* !META_BACK_PRINT_CONNTREE */
48 
49 /*
50  * A a_metasingleconn_t can be in the following, mutually exclusive states:
51  *
52  *	- none			(0x0U)
53  *	- creating		META_BACK_FCONN_CREATING
54  *	- initialized		META_BACK_FCONN_INITED
55  *	- binding		LDAP_BACK_FCONN_BINDING
56  *	- bound/anonymous	LDAP_BACK_FCONN_ISBOUND/LDAP_BACK_FCONN_ISANON
57  *
58  * possible modifiers are:
59  *
60  *	- privileged		LDAP_BACK_FCONN_ISPRIV
61  *	- privileged, TLS	LDAP_BACK_FCONN_ISTLS
62  *	- subjected to idassert	LDAP_BACK_FCONN_ISIDASR
63  *	- tainted		LDAP_BACK_FCONN_TAINTED
64  */
65 
66 #define META_BACK_FCONN_INITED		(0x00100000U)
67 #define META_BACK_FCONN_CREATING	(0x00200000U)
68 #define META_BACK_FCONN_INVALID	        (0x00400000U)
69 
70 #define	META_BACK_CONN_INITED(lc)		LDAP_BACK_CONN_ISSET((lc), META_BACK_FCONN_INITED)
71 #define	META_BACK_CONN_INITED_SET(lc)		LDAP_BACK_CONN_SET((lc), META_BACK_FCONN_INITED)
72 #define	META_BACK_CONN_INITED_CLEAR(lc)		LDAP_BACK_CONN_CLEAR((lc), META_BACK_FCONN_INITED)
73 #define	META_BACK_CONN_INITED_CPY(lc, mlc)	LDAP_BACK_CONN_CPY((lc), META_BACK_FCONN_INITED, (mlc))
74 #define	META_BACK_CONN_CREATING(lc)		LDAP_BACK_CONN_ISSET((lc), META_BACK_FCONN_CREATING)
75 #define	META_BACK_CONN_CREATING_SET(lc)		LDAP_BACK_CONN_SET((lc), META_BACK_FCONN_CREATING)
76 #define	META_BACK_CONN_CREATING_CLEAR(lc)	LDAP_BACK_CONN_CLEAR((lc), META_BACK_FCONN_CREATING)
77 #define	META_BACK_CONN_CREATING_CPY(lc, mlc)	LDAP_BACK_CONN_CPY((lc), META_BACK_FCONN_CREATING, (mlc))
78 #define	META_BACK_CONN_INVALID(lc)		LDAP_BACK_CONN_ISSET((lc), META_BACK_FCONN_INVALID)
79 #define	META_BACK_CONN_INVALID_SET(lc)		LDAP_BACK_CONN_SET((lc), META_BACK_FCONN_INVALID)
80 #define	META_BACK_CONN_INVALID_CLEAR(lc)	LDAP_BACK_CONN_CLEAR((lc), META_BACK_FCONN_INVALID)
81 
82 struct a_metainfo_t;
83 struct a_metaconn_t;
84 struct a_metatarget_t;
85 #define	META_NOT_CANDIDATE		((ber_tag_t)0x0)
86 #define	META_CANDIDATE			((ber_tag_t)0x1)
87 #define	META_BINDING			((ber_tag_t)0x2)
88 #define	META_RETRYING			((ber_tag_t)0x4)
89 
90 typedef struct bm_context_t {
91 	LDAP_STAILQ_ENTRY(bm_context_t) bc_next;
92 	struct a_metaconn_t *bc_mc;
93 	time_t			timeout;
94 	time_t                  stoptime;
95 	ldap_back_send_t	sendok;
96 	ldap_back_send_t	retrying;
97 	int candidate_match;
98 	volatile int bc_active;
99 	int searchtime;	/* stoptime is a search timelimit */
100 	int is_ok;
101 	int is_root;
102 	volatile sig_atomic_t bc_invalid;
103 	SlapReply		rs;
104 	Operation		*op;
105 	Operation               copy_op;
106 	LDAPControl	        **ctrls;
107 	int                     *msgids;
108 	int                     *nretries;  /* number of times to retry a failed send on an msc */
109 	struct berval	        c_peer_name; /* peer name of original op->o_conn*/
110 	SlapReply               *candidates;
111 } bm_context_t;
112 
113 typedef struct a_metasingleconn_t {
114 #define META_CND_ISSET(rs,f)		( ( (rs)->sr_tag & (f) ) == (f) )
115 #define META_CND_SET(rs,f)		( (rs)->sr_tag |= (f) )
116 #define META_CND_CLEAR(rs,f)		( (rs)->sr_tag &= ~(f) )
117 
118 #define META_CANDIDATE_RESET(rs)	( (rs)->sr_tag = 0 )
119 #define META_IS_CANDIDATE(rs)		META_CND_ISSET( (rs), META_CANDIDATE )
120 #define META_CANDIDATE_SET(rs)		META_CND_SET( (rs), META_CANDIDATE )
121 #define META_CANDIDATE_CLEAR(rs)	META_CND_CLEAR( (rs), META_CANDIDATE )
122 #define META_IS_BINDING(rs)		META_CND_ISSET( (rs), META_BINDING )
123 #define META_BINDING_SET(rs)		META_CND_SET( (rs), META_BINDING )
124 #define META_BINDING_CLEAR(rs)		META_CND_CLEAR( (rs), META_BINDING )
125 #define META_IS_RETRYING(rs)		META_CND_ISSET( (rs), META_RETRYING )
126 #define META_RETRYING_SET(rs)		META_CND_SET( (rs), META_RETRYING )
127 #define META_RETRYING_CLEAR(rs)		META_CND_CLEAR( (rs), META_RETRYING )
128 
129 	LDAP            	*msc_ld;
130 	LDAP            	*msc_ldr;
131 	time_t			msc_time;
132 	time_t                  msc_binding_time;
133 	time_t                  msc_result_time;
134 	struct berval          	msc_bound_ndn;
135 	struct berval		msc_cred;
136 	unsigned		msc_mscflags;
137 
138 	/* NOTE: lc_lcflags is redefined to msc_mscflags to reuse the macros
139 	 * defined for back-ldap */
140 #define	lc_lcflags		msc_mscflags
141 	volatile int msc_active;
142 		/* Connection for the select */
143 	Connection *conn;
144 } a_metasingleconn_t;
145 
146 typedef struct a_metaconn_t {
147 	ldapconn_base_t		lc_base;
148 #define	mc_base			lc_base
149 //#define	mc_conn			mc_base.lcb_conn
150 //#define	mc_local_ndn		mc_base.lcb_local_ndn
151 //#define	mc_refcnt		mc_base.lcb_refcnt
152 //#define	mc_create_time		mc_base.lcb_create_time
153 //#define	mc_time			mc_base.lcb_time
154 
155 	LDAP_TAILQ_ENTRY(a_metaconn_t)	mc_q;
156 
157 	/* NOTE: msc_mscflags is used to recycle the #define
158 	 * in metasingleconn_t */
159 	unsigned		msc_mscflags;
160 	int	mc_active;
161 
162 	/*
163 	 * means that the connection is bound;
164 	 * of course only one target actually is ...
165 	 */
166 	int             	mc_authz_target;
167 #define META_BOUND_NONE		(-1)
168 #define META_BOUND_ALL		(-2)
169 
170 	struct a_metainfo_t	*mc_info;
171 
172 	int pending_ops;
173 	ldap_pvt_thread_mutex_t	mc_om_mutex;
174 	/* queue for pending operations */
175 	LDAP_STAILQ_HEAD(BCList, bm_context_t) mc_om_list;
176 	/* supersedes the connection stuff */
177 	a_metasingleconn_t	*mc_conns;
178 } a_metaconn_t;
179 
180 typedef enum meta_st_t {
181 #if 0 /* todo */
182 	META_ST_EXACT = LDAP_SCOPE_BASE,
183 #endif
184 	META_ST_SUBTREE = LDAP_SCOPE_SUBTREE,
185 	META_ST_SUBORDINATE = LDAP_SCOPE_SUBORDINATE,
186 	META_ST_REGEX /* last + 1 */
187 } meta_st_t;
188 
189 typedef struct a_metasubtree_t {
190 	meta_st_t ms_type;
191 	union {
192 		struct berval msu_dn;
193 		struct {
194 			struct berval msr_regex_pattern;
195 			regex_t msr_regex;
196 		} msu_regex;
197 	} ms_un;
198 #define ms_dn ms_un.msu_dn
199 #define ms_regex ms_un.msu_regex.msr_regex
200 #define ms_regex_pattern ms_un.msu_regex.msr_regex_pattern
201 
202 	struct a_metasubtree_t *ms_next;
203 } a_metasubtree_t;
204 
205 typedef struct metafilter_t {
206 	struct metafilter_t *mf_next;
207 	struct berval mf_regex_pattern;
208 	regex_t mf_regex;
209 } metafilter_t;
210 
211 typedef struct a_metacommon_t {
212 	int				mc_version;
213 	int				mc_nretries;
214 #define META_RETRY_UNDEFINED	(-2)
215 #define META_RETRY_FOREVER	(-1)
216 #define META_RETRY_NEVER	(0)
217 #define META_RETRY_DEFAULT	(2)
218 
219 	unsigned		mc_flags;
220 #define	META_BACK_CMN_ISSET(mc,f)		( ( (mc)->mc_flags & (f) ) == (f) )
221 #define	META_BACK_CMN_QUARANTINE(mc)		META_BACK_CMN_ISSET( (mc), LDAP_BACK_F_QUARANTINE )
222 #define	META_BACK_CMN_CHASE_REFERRALS(mc)	META_BACK_CMN_ISSET( (mc), LDAP_BACK_F_CHASE_REFERRALS )
223 #define	META_BACK_CMN_NOREFS(mc)		META_BACK_CMN_ISSET( (mc), LDAP_BACK_F_NOREFS )
224 #define	META_BACK_CMN_NOUNDEFFILTER(mc)		META_BACK_CMN_ISSET( (mc), LDAP_BACK_F_NOUNDEFFILTER )
225 #define	META_BACK_CMN_SAVECRED(mc)		META_BACK_CMN_ISSET( (mc), LDAP_BACK_F_SAVECRED )
226 #define	META_BACK_CMN_ST_REQUEST(mc)		META_BACK_CMN_ISSET( (mc), LDAP_BACK_F_ST_REQUEST )
227 
228 #ifdef SLAPD_META_CLIENT_PR
229 	/*
230 	 * client-side paged results:
231 	 * -1: accept unsolicited paged results responses
232 	 *  0: off
233 	 * >0: always request paged results with size == mt_ps
234 	 */
235 #define META_CLIENT_PR_DISABLE			(0)
236 #define META_CLIENT_PR_ACCEPT_UNSOLICITED	(-1)
237 	ber_int_t		mc_ps;
238 #endif /* SLAPD_META_CLIENT_PR */
239 
240 	slap_retry_info_t	mc_quarantine;
241 	time_t			mc_network_timeout;
242 	struct timeval	mc_bind_timeout;
243 #define META_BIND_TIMEOUT	LDAP_BACK_RESULT_UTIMEOUT
244 	time_t			mc_timeout[ SLAP_OP_LAST ];
245 } a_metacommon_t;
246 
247 typedef struct a_metatarget_t {
248 	char			*mt_uri;
249 	ldap_pvt_thread_mutex_t	mt_uri_mutex;
250 
251 	/* TODO: we might want to enable different strategies
252 	 * for different targets */
253 	LDAP_REBIND_PROC	*mt_rebind_f;
254 	LDAP_URLLIST_PROC	*mt_urllist_f;
255 	void			*mt_urllist_p;
256 
257 	metafilter_t	*mt_filter;
258 	a_metasubtree_t		*mt_subtree;
259 	/* F: subtree-include; T: subtree-exclude */
260 	int			mt_subtree_exclude;
261 
262 	int			mt_scope;
263 
264 	struct berval		mt_psuffix;		/* pretty suffix */
265 	struct berval		mt_nsuffix;		/* normalized suffix */
266 
267 	struct berval		mt_lsuffixm;	/* local suffix for massage */
268 	struct berval		mt_rsuffixm;	/* remote suffix for massage */
269 
270 	struct berval		mt_binddn;
271 	struct berval		mt_bindpw;
272 
273 	/* we only care about the TLS options here */
274 	slap_bindconf		mt_tls;
275 
276 	slap_idassert_t		mt_idassert;
277 #define	mt_idassert_mode	mt_idassert.si_mode
278 #define	mt_idassert_authcID	mt_idassert.si_bc.sb_authcId
279 #define	mt_idassert_authcDN	mt_idassert.si_bc.sb_binddn
280 #define	mt_idassert_passwd	mt_idassert.si_bc.sb_cred
281 #define	mt_idassert_authzID	mt_idassert.si_bc.sb_authzId
282 #define	mt_idassert_authmethod	mt_idassert.si_bc.sb_method
283 #define	mt_idassert_sasl_mech	mt_idassert.si_bc.sb_saslmech
284 #define	mt_idassert_sasl_realm	mt_idassert.si_bc.sb_realm
285 #define	mt_idassert_secprops	mt_idassert.si_bc.sb_secprops
286 #define	mt_idassert_tls		mt_idassert.si_bc.sb_tls
287 #define	mt_idassert_flags	mt_idassert.si_flags
288 #define	mt_idassert_authz	mt_idassert.si_authz
289 
290 	sig_atomic_t		mt_isquarantined;
291 	ldap_pvt_thread_mutex_t	mt_quarantine_mutex;
292 
293 	a_metacommon_t	mt_mc;
294 #define	mt_nretries	mt_mc.mc_nretries
295 #define	mt_flags	mt_mc.mc_flags
296 #define	mt_version	mt_mc.mc_version
297 #define	mt_ps		mt_mc.mc_ps
298 #define	mt_network_timeout	mt_mc.mc_network_timeout
299 #define	mt_bind_timeout	mt_mc.mc_bind_timeout
300 #define	mt_timeout	mt_mc.mc_timeout
301 #define	mt_quarantine	mt_mc.mc_quarantine
302 
303 #define	META_BACK_TGT_ISSET(mt,f)		( ( (mt)->mt_flags & (f) ) == (f) )
304 #define	META_BACK_TGT_ISMASK(mt,m,f)		( ( (mt)->mt_flags & (m) ) == (f) )
305 
306 #define META_BACK_TGT_SAVECRED(mt)		META_BACK_TGT_ISSET( (mt), LDAP_BACK_F_SAVECRED )
307 
308 #define META_BACK_TGT_USE_TLS(mt)		META_BACK_TGT_ISSET( (mt), LDAP_BACK_F_USE_TLS )
309 #define META_BACK_TGT_PROPAGATE_TLS(mt)		META_BACK_TGT_ISSET( (mt), LDAP_BACK_F_PROPAGATE_TLS )
310 #define META_BACK_TGT_TLS_CRITICAL(mt)		META_BACK_TGT_ISSET( (mt), LDAP_BACK_F_TLS_CRITICAL )
311 
312 #define META_BACK_TGT_CHASE_REFERRALS(mt)	META_BACK_TGT_ISSET( (mt), LDAP_BACK_F_CHASE_REFERRALS )
313 
314 #define	META_BACK_TGT_T_F(mt)			META_BACK_TGT_ISMASK( (mt), LDAP_BACK_F_T_F_MASK, LDAP_BACK_F_T_F )
315 #define	META_BACK_TGT_T_F_DISCOVER(mt)		META_BACK_TGT_ISMASK( (mt), LDAP_BACK_F_T_F_MASK2, LDAP_BACK_F_T_F_DISCOVER )
316 
317 #define	META_BACK_TGT_ABANDON(mt)		META_BACK_TGT_ISMASK( (mt), LDAP_BACK_F_CANCEL_MASK, LDAP_BACK_F_CANCEL_ABANDON )
318 #define	META_BACK_TGT_IGNORE(mt)		META_BACK_TGT_ISMASK( (mt), LDAP_BACK_F_CANCEL_MASK, LDAP_BACK_F_CANCEL_IGNORE )
319 #define	META_BACK_TGT_CANCEL(mt)		META_BACK_TGT_ISMASK( (mt), LDAP_BACK_F_CANCEL_MASK, LDAP_BACK_F_CANCEL_EXOP )
320 #define	META_BACK_TGT_CANCEL_DISCOVER(mt)	META_BACK_TGT_ISMASK( (mt), LDAP_BACK_F_CANCEL_MASK2, LDAP_BACK_F_CANCEL_EXOP_DISCOVER )
321 #define	META_BACK_TGT_QUARANTINE(mt)		META_BACK_TGT_ISSET( (mt), LDAP_BACK_F_QUARANTINE )
322 
323 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
324 #define	META_BACK_TGT_ST_REQUEST(mt)		META_BACK_TGT_ISSET( (mt), LDAP_BACK_F_ST_REQUEST )
325 #define	META_BACK_TGT_ST_RESPONSE(mt)		META_BACK_TGT_ISSET( (mt), LDAP_BACK_F_ST_RESPONSE )
326 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */
327 
328 #define	META_BACK_TGT_NOREFS(mt)		META_BACK_TGT_ISSET( (mt), LDAP_BACK_F_NOREFS )
329 #define	META_BACK_TGT_NOUNDEFFILTER(mt)		META_BACK_TGT_ISSET( (mt), LDAP_BACK_F_NOUNDEFFILTER )
330 
331 #define META_BACK_CFG_MAX_PENDING_OPS		0x80
332 #define META_BACK_CFG_MAX_TARGET_CONNS		0xFF
333 #define META_BACK_CFG_DEFAULT_OPS_TIMEOUT	0x02
334 
335 /* the interval of the timeout checking loop in microseconds
336  * possibly make this configurable? */
337 #define META_BACK_CFG_MAX_TIMEOUT_LOOP		0x70000
338 	slap_mask_t		mt_rep_flags;
339 	int			mt_timeout_ops;
340 } a_metatarget_t;
341 
342 typedef struct a_metadncache_t {
343 	ldap_pvt_thread_mutex_t mutex;
344 	Avlnode			*tree;
345 
346 #define META_DNCACHE_DISABLED   (0)
347 #define META_DNCACHE_FOREVER    ((time_t)(-1))
348 	time_t			ttl;  /* seconds; 0: no cache, -1: no expiry */
349 } a_metadncache_t;
350 
351 typedef struct a_metacandidates_t {
352 	int			mc_ntargets;
353 	SlapReply		*mc_candidates;
354 } a_metacandidates_t;
355 
356 /*
357  * Hook to allow mucking with a_metainfo_t/a_metatarget_t when quarantine is over
358  */
359 typedef int (*asyncmeta_quarantine_f)( struct a_metainfo_t *, int target, void * );
360 
361 struct meta_out_message_t;
362 
363 typedef struct a_metainfo_t {
364 	int			mi_ntargets;
365 	int			mi_defaulttarget;
366 #define META_DEFAULT_TARGET_NONE	(-1)
367 
368 #define	mi_nretries	mi_mc.mc_nretries
369 #define	mi_flags	mi_mc.mc_flags
370 #define	mi_version	mi_mc.mc_version
371 #define	mi_ps		mi_mc.mc_ps
372 #define	mi_network_timeout	mi_mc.mc_network_timeout
373 #define	mi_bind_timeout	mi_mc.mc_bind_timeout
374 #define	mi_timeout	mi_mc.mc_timeout
375 #define	mi_quarantine	mi_mc.mc_quarantine
376 
377 	a_metatarget_t		**mi_targets;
378 	a_metacandidates_t	*mi_candidates;
379 
380 	LDAP_REBIND_PROC	*mi_rebind_f;
381 	LDAP_URLLIST_PROC	*mi_urllist_f;
382 
383 	a_metadncache_t		mi_cache;
384 
385 	struct {
386 		int						mic_num;
387 		LDAP_TAILQ_HEAD(mc_conn_priv_q, a_metaconn_t)	mic_priv;
388 	}			mi_conn_priv[ LDAP_BACK_PCONN_LAST ];
389 	int			mi_conn_priv_max;
390 
391 	/* NOTE: quarantine uses the connection mutex */
392 	asyncmeta_quarantine_f	mi_quarantine_f;
393 	void			*mi_quarantine_p;
394 
395 #define	li_flags		mi_flags
396 /* uses flags as defined in <back-ldap/back-ldap.h> */
397 #define	META_BACK_F_ONERR_STOP		LDAP_BACK_F_ONERR_STOP
398 #define	META_BACK_F_ONERR_REPORT	(0x02000000U)
399 #define	META_BACK_F_ONERR_MASK		(META_BACK_F_ONERR_STOP|META_BACK_F_ONERR_REPORT)
400 #define	META_BACK_F_DEFER_ROOTDN_BIND	(0x04000000U)
401 #define	META_BACK_F_PROXYAUTHZ_ALWAYS	(0x08000000U)	/* users always proxyauthz */
402 #define	META_BACK_F_PROXYAUTHZ_ANON	(0x10000000U)	/* anonymous always proxyauthz */
403 #define	META_BACK_F_PROXYAUTHZ_NOANON	(0x20000000U)	/* anonymous remains anonymous */
404 
405 #define	META_BACK_ONERR_STOP(mi)	LDAP_BACK_ISSET( (mi), META_BACK_F_ONERR_STOP )
406 #define	META_BACK_ONERR_REPORT(mi)	LDAP_BACK_ISSET( (mi), META_BACK_F_ONERR_REPORT )
407 #define	META_BACK_ONERR_CONTINUE(mi)	( !LDAP_BACK_ISSET( (mi), META_BACK_F_ONERR_MASK ) )
408 
409 #define META_BACK_DEFER_ROOTDN_BIND(mi)	LDAP_BACK_ISSET( (mi), META_BACK_F_DEFER_ROOTDN_BIND )
410 #define META_BACK_PROXYAUTHZ_ALWAYS(mi)	LDAP_BACK_ISSET( (mi), META_BACK_F_PROXYAUTHZ_ALWAYS )
411 #define META_BACK_PROXYAUTHZ_ANON(mi)	LDAP_BACK_ISSET( (mi), META_BACK_F_PROXYAUTHZ_ANON )
412 #define META_BACK_PROXYAUTHZ_NOANON(mi)	LDAP_BACK_ISSET( (mi), META_BACK_F_PROXYAUTHZ_NOANON )
413 
414 #define META_BACK_QUARANTINE(mi)	LDAP_BACK_ISSET( (mi), LDAP_BACK_F_QUARANTINE )
415 
416 	time_t			mi_idle_timeout;
417 	struct re_s *mi_task;
418 
419 	a_metacommon_t	mi_mc;
420 	ldap_extra_t	*mi_ldap_extra;
421 
422 	int                    mi_max_timeout_ops;
423 	int                    mi_max_pending_ops;
424 	int                    mi_max_target_conns;
425 	/* mutex for access to the connection structures */
426 	ldap_pvt_thread_mutex_t	mi_mc_mutex;
427 	int                    mi_num_conns;
428 	int                    mi_next_conn;
429 	a_metaconn_t          *mi_conns;
430 
431 	struct berval		mi_suffix;
432 } a_metainfo_t;
433 
434 typedef enum meta_op_type {
435 	META_OP_ALLOW_MULTIPLE = 0,
436 	META_OP_REQUIRE_SINGLE,
437 	META_OP_REQUIRE_ALL
438 } meta_op_type;
439 
440 /* Whatever context asyncmeta_dn_massage needs... */
441 typedef struct a_dncookie {
442 	Operation		*op;
443 	struct a_metatarget_t	*target;
444 	void	*memctx;
445 	int	to_from;
446 } a_dncookie;
447 
448 
449 #define MASSAGE_REQ	0
450 #define MASSAGE_REP	1
451 
452 extern void
453 asyncmeta_dn_massage(a_dncookie *dc, struct berval *dn,
454 	struct berval *res);
455 
456 extern void
457 asyncmeta_filter_map_rewrite(
458 	a_dncookie	*dc,
459 	Filter		*f,
460 	struct berval	*fstr );
461 
462 extern void
463 asyncmeta_back_referral_result_rewrite(
464 	a_dncookie	*dc,
465 	BerVarray	a_vals );
466 
467 extern a_metaconn_t *
468 asyncmeta_getconn(
469 	Operation		*op,
470 	SlapReply		*rs,
471 	SlapReply               *candidates,
472 	int			*candidate,
473 	ldap_back_send_t	sendok,
474 	int                     alloc_new);
475 
476 
477 extern int
478 asyncmeta_init_one_conn(
479 	Operation		*op,
480 	SlapReply		*rs,
481 	a_metaconn_t		*mc,
482 	int			candidate,
483 	int			ispriv,
484 	ldap_back_send_t	sendok,
485 	int			dolock );
486 
487 extern void
488 asyncmeta_quarantine(
489 	Operation		*op,
490 	a_metainfo_t            *mi,
491 	SlapReply		*rs,
492 	int			candidate );
493 
494 extern int
495 asyncmeta_proxy_authz_cred(
496 	a_metaconn_t		*mc,
497 	int			candidate,
498 	Operation		*op,
499 	SlapReply		*rs,
500 	ldap_back_send_t	sendok,
501 	struct berval		*binddn,
502 	struct berval		*bindcred,
503 	int			*method );
504 
505 extern int
506 asyncmeta_controls_add(
507 	Operation	*op,
508 	SlapReply	*rs,
509 	a_metaconn_t	*mc,
510 	int		candidate,
511 	int             isroot,
512 	LDAPControl	***pctrls );
513 
514 extern int
515 asyncmeta_LTX_init_module(
516 	int			argc,
517 	char			*argv[] );
518 
519 /*
520  * Candidate stuff
521  */
522 extern int
523 asyncmeta_is_candidate(
524 	a_metatarget_t		*mt,
525 	struct berval		*ndn,
526 	int			scope );
527 
528 extern int
529 asyncmeta_select_unique_candidate(
530 	a_metainfo_t		*mi,
531 	struct berval		*ndn );
532 
533 extern int
534 asyncmeta_clear_unused_candidates(
535 	Operation		*op,
536 	int			candidate,
537 	a_metaconn_t            *mc,
538 	SlapReply	*candidates);
539 
540 /*
541  * Dn cache stuff (experimental)
542  */
543 extern int
544 asyncmeta_dncache_cmp(
545 	const void		*c1,
546 	const void		*c2 );
547 
548 extern int
549 asyncmeta_dncache_dup(
550 	void			*c1,
551 	void			*c2 );
552 
553 #define META_TARGET_NONE	(-1)
554 #define META_TARGET_MULTIPLE	(-2)
555 extern int
556 asyncmeta_dncache_get_target(
557 	a_metadncache_t		*cache,
558 	struct berval		*ndn );
559 
560 extern int
561 meta_dncache_update_entry(
562 	a_metadncache_t		*cache,
563 	struct berval		*ndn,
564 	int			target );
565 
566 extern int
567 asyncmeta_dncache_delete_entry(
568 	a_metadncache_t		*cache,
569 	struct berval		*ndn );
570 
571 extern void
572 asyncmeta_dncache_free( void *entry );
573 
574 extern int
575 asyncmeta_subtree_destroy( a_metasubtree_t *ms );
576 
577 extern void
578 asyncmeta_filter_destroy( metafilter_t *mf );
579 
580 extern int
581 asyncmeta_target_finish( a_metainfo_t *mi, a_metatarget_t *mt,
582 	const char *log, char *msg, size_t msize
583 );
584 
585 
586 extern LDAP_REBIND_PROC		asyncmeta_back_default_rebind;
587 extern LDAP_URLLIST_PROC	asyncmeta_back_default_urllist;
588 
589 /* IGNORE means that target does not (no longer) participate
590  * in the search;
591  * NOTREADY means the search on that target has not been initialized yet
592  */
593 #define	META_MSGID_IGNORE	(-1)
594 #define	META_MSGID_NEED_BIND	(-2)
595 #define	META_MSGID_CONNECTING	(-3)
596 #define META_MSGID_UNDEFINED    (-4)
597 #define META_MSGID_GOT_BIND     (-5)
598 
599 typedef enum meta_search_candidate_t {
600 	META_SEARCH_UNDEFINED = -2,
601 	META_SEARCH_ERR = -1,
602 	META_SEARCH_NOT_CANDIDATE,
603 	META_SEARCH_CANDIDATE,
604 	META_SEARCH_BINDING,
605 	META_SEARCH_NEED_BIND,
606 	META_SEARCH_CONNECTING
607 } meta_search_candidate_t;
608 
609 Operation* asyncmeta_copy_op(Operation *op);
610 void asyncmeta_clear_bm_context(bm_context_t *bc);
611 
612 int asyncmeta_add_message_queue(a_metaconn_t *mc, bm_context_t *bc);
613 void asyncmeta_drop_bc(a_metaconn_t *mc, bm_context_t *bc);
614 void asyncmeta_drop_bc_from_fconn(bm_context_t *bc);
615 
616 bm_context_t *
617 asyncmeta_find_message(ber_int_t msgid, a_metaconn_t *mc, int candidate);
618 
619 void* asyncmeta_op_handle_result(void *ctx, void *arg);
620 int asyncmeta_back_cleanup( Operation *op, SlapReply *rs, bm_context_t *bm );
621 
622 int
623 asyncmeta_clear_one_msc(
624 	Operation	*op,
625 	a_metaconn_t	*msc,
626 	int		candidate,
627 	int             unbind,
628 	const char *          caller);
629 
630 a_metaconn_t *
631 asyncmeta_get_next_mc( a_metainfo_t *mi );
632 
633 void* asyncmeta_timeout_loop(void *ctx, void *arg);
634 
635 int
636 asyncmeta_start_timeout_loop(a_metatarget_t *mt, a_metainfo_t *mi);
637 
638 void asyncmeta_set_msc_time(a_metasingleconn_t *msc);
639 
640 int asyncmeta_back_cancel(
641 	a_metaconn_t	*mc,
642 	Operation		*op,
643 	ber_int_t		msgid,
644 	int				candidate );
645 
646 void
647 asyncmeta_send_result(bm_context_t* bc, int error, char *text);
648 
649 int asyncmeta_new_bm_context(Operation *op,
650 			     SlapReply *rs,
651 			     bm_context_t **new_bc,
652 			     int ntargets,
653 			     a_metainfo_t       *mi);
654 
655 int asyncmeta_start_listeners(a_metaconn_t *mc, SlapReply *candidates,  bm_context_t *bc);
656 int asyncmeta_start_one_listener(a_metaconn_t *mc, SlapReply *candidates,  bm_context_t *bc, int candidate);
657 
658 meta_search_candidate_t
659 asyncmeta_back_search_start(
660 	Operation             *op,
661 	SlapReply             *rs,
662 	a_metaconn_t          *mc,
663 	bm_context_t          *bc,
664 	int                   candidate,
665 	struct berval	      *prcookie,
666 	ber_int_t	      prsize,
667 	int do_lock);
668 
669 meta_search_candidate_t
670 asyncmeta_dobind_init(
671 	Operation            *op,
672 	SlapReply            *rs,
673 	bm_context_t         *bc,
674 	a_metaconn_t         *mc,
675 	int                  candidate);
676 
677 meta_search_candidate_t
678 asyncmeta_dobind_init_with_retry(
679 	Operation            *op,
680 	SlapReply            *rs,
681 	bm_context_t         *bc,
682 	a_metaconn_t         *mc,
683 	int                  candidate);
684 
685 meta_search_candidate_t
686 asyncmeta_back_add_start(Operation *op,
687 			 SlapReply *rs,
688 			 a_metaconn_t *mc,
689 			 bm_context_t *bc,
690 			 int candidate,
691 			 int do_lock);
692 meta_search_candidate_t
693 asyncmeta_back_modify_start(Operation *op,
694 			    SlapReply *rs,
695 			    a_metaconn_t *mc,
696 			    bm_context_t *bc,
697 			    int candidate,
698 			    int do_lock);
699 
700 meta_search_candidate_t
701 asyncmeta_back_modrdn_start(Operation *op,
702 			    SlapReply *rs,
703 			    a_metaconn_t *mc,
704 			    bm_context_t *bc,
705 			    int candidate,
706 			    int do_lock);
707 meta_search_candidate_t
708 asyncmeta_back_delete_start(Operation *op,
709 			    SlapReply *rs,
710 			    a_metaconn_t *mc,
711 			    bm_context_t *bc,
712 			    int candidate,
713 			    int do_lock);
714 
715 meta_search_candidate_t
716 asyncmeta_back_compare_start(Operation *op,
717 			     SlapReply *rs,
718 			     a_metaconn_t *mc,
719 			     bm_context_t *bc,
720 			     int candidate,
721 			     int do_lock);
722 
723 bm_context_t *
724 asyncmeta_bc_in_queue(a_metaconn_t *mc,
725 		      bm_context_t *bc);
726 
727 int
728 asyncmeta_error_cleanup(Operation *op,
729 			SlapReply *rs,
730 			bm_context_t *bc,
731 			a_metaconn_t *mc,
732 			int candidate);
733 
734 int
735 asyncmeta_reset_msc(Operation	*op,
736 		    a_metaconn_t	*mc,
737 		    int		candidate,
738 		    int             unbind,
739 		    const char *caller);
740 
741 
742 void
743 asyncmeta_back_conn_free(
744 	            void 		*v_mc );
745 
746 void asyncmeta_log_msc(a_metasingleconn_t *msc);
747 void asyncmeta_log_conns(a_metainfo_t *mi);
748 
749 void asyncmeta_get_timestamp(char *buf);
750 
751 int
752 asyncmeta_dncache_update_entry(a_metadncache_t	*cache,
753 			       struct berval	*ndn,
754 			       int 		target );
755 
756 void
757 asyncmeta_dnattr_result_rewrite(a_dncookie		*dc,
758 				BerVarray		a_vals);
759 
760 void
761 asyncmeta_referral_result_rewrite(a_dncookie		*dc,
762 				  BerVarray		a_vals);
763 
764 meta_search_candidate_t
765 asyncmeta_send_all_pending_ops(a_metaconn_t *mc,
766 			       int          candidate,
767 			       void         *ctx,
768 			       int          dolock);
769 meta_search_candidate_t
770 asyncmeta_return_bind_errors(a_metaconn_t *mc,
771 			     int          candidate,
772 			     SlapReply    *bind_result,
773 			     void         *ctx,
774 			     int          dolock);
775 
776 /* The the maximum time in seconds after a result has been received on a connection,
777  * after which it can be reset if a sender error occurs. Should this be configurable? */
778 #define META_BACK_RESULT_INTERVAL (2)
779 
780 extern int asyncmeta_debug;
781 
782 LDAP_END_DECL
783 
784 #endif /* SLAPD_ASYNCMETA_H */
785