1 /*
2  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*
7  * The contents of this file are subject to the Netscape Public
8  * License Version 1.1 (the "License"); you may not use this file
9  * except in compliance with the License. You may obtain a copy of
10  * the License at http://www.mozilla.org/NPL/
11  *
12  * Software distributed under the License is distributed on an "AS
13  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14  * implied. See the License for the specific language governing
15  * rights and limitations under the License.
16  *
17  * The Original Code is Mozilla Communicator client code, released
18  * March 31, 1998.
19  *
20  * The Initial Developer of the Original Code is Netscape
21  * Communications Corporation. Portions created by Netscape are
22  * Copyright (C) 1998-1999 Netscape Communications Corporation. All
23  * Rights Reserved.
24  *
25  * Contributor(s):
26  */
27 
28 #ifndef _LDAPINT_H
29 #define _LDAPINT_H
30 
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <errno.h>
35 #include <time.h>
36 #include <fcntl.h>
37 #ifdef hpux
38 #include <strings.h>
39 #endif /* hpux */
40 
41 #ifdef _WINDOWS
42 #  define FD_SETSIZE		256	/* number of connections we support */
43 #  define WIN32_LEAN_AND_MEAN
44 # include <windows.h>
45 #elif defined(macintosh)
46 #include "ldap-macos.h"
47 #elif defined(XP_OS2)
48 #include <os2sock.h>
49 #else /* _WINDOWS */
50 # include <sys/time.h>
51 # include <sys/types.h>
52 # include <sys/socket.h>
53 # include <netinet/in.h>
54 # include <arpa/inet.h>
55 # include <netdb.h>
56 #if !defined(hpux) && !defined(SUNOS4) && !defined(LINUX)
57 # include <sys/select.h>
58 #endif /* !defined(hpux) and others */
59 #endif /* _WINDOWS */
60 
61 #if defined(IRIX)
62 #include <bstring.h>
63 #endif /* IRIX */
64 
65 #define NSLBERI_LBER_INT_FRIEND
66 #ifdef macintosh
67 #include "lber-int.h"
68 #elif defined(_SOLARIS_SDK)
69 #include "../ber/lber-int.h"
70 #else /* _SOLARIS_SDK */
71 #include "../liblber/lber-int.h"
72 #endif /* macintosh */
73 
74 #include "ldap.h"
75 #include "ldaprot.h"
76 #include "ldaplog.h"
77 #include "portable.h"
78 #include "regex.h"
79 
80 #ifdef LDAP_ASYNC_IO
81 #ifdef NEED_FILIO
82 #include <sys/filio.h>		/* to get FIONBIO for ioctl() call */
83 #else /* NEED_FILIO */
84 #if !defined( _WINDOWS) && !defined (macintosh)
85 #include <sys/ioctl.h>		/* to get FIONBIO for ioctl() call */
86 #endif /* _WINDOWS && macintosh */
87 #endif /* NEED_FILIO */
88 #endif /* LDAP_ASYNC_IO */
89 
90 #ifdef USE_SYSCONF
91 #  include <unistd.h>
92 #endif /* USE_SYSCONF */
93 
94 #ifdef _SOLARIS_SDK
95 #include <libintl.h>
96 #endif
97 #ifdef LDAP_SASLIO_HOOKS
98 #include <sasl/sasl.h>
99 #define SASL_MAX_BUFF_SIZE	65536
100 #define SASL_MIN_BUFF_SIZE	4096
101 #endif
102 
103 #if !defined(_WINDOWS) && !defined(macintosh) && !defined(LINUX) && !defined(BSDI)
104 #define NSLDAPI_HAVE_POLL	1
105 #endif
106 
107 /* SSL version, or 0 if not built with SSL */
108 #if defined(NET_SSL)
109 #  define SSL_VERSION 3
110 #else
111 #  define SSL_VERSION 0
112 #endif
113 
114 
115 #define LDAP_URL_URLCOLON	"URL:"
116 #define LDAP_URL_URLCOLON_LEN	4
117 
118 #define LDAP_LDAP_REF_STR	LDAP_URL_PREFIX
119 #define LDAP_LDAP_REF_STR_LEN	LDAP_URL_PREFIX_LEN
120 #define LDAP_LDAPS_REF_STR	LDAPS_URL_PREFIX
121 #define LDAP_LDAPS_REF_STR_LEN	LDAPS_URL_PREFIX_LEN
122 
123 /* default limit on nesting of referrals */
124 #define LDAP_DEFAULT_REFHOPLIMIT	5
125 #ifdef LDAP_DNS
126 #define LDAP_DX_REF_STR		"dx://"
127 #define LDAP_DX_REF_STR_LEN	5
128 #endif /* LDAP_DNS */
129 
130 typedef enum {
131     LDAP_CACHE_LOCK,
132     LDAP_MEMCACHE_LOCK,
133     LDAP_MSGID_LOCK,
134     LDAP_REQ_LOCK,
135     LDAP_RESP_LOCK,
136     LDAP_ABANDON_LOCK,
137     LDAP_CTRL_LOCK,
138     LDAP_OPTION_LOCK,
139     LDAP_ERR_LOCK,
140     LDAP_CONN_LOCK,
141     LDAP_IOSTATUS_LOCK,		/* serializes access to ld->ld_iostatus */
142     LDAP_RESULT_LOCK,
143     LDAP_PEND_LOCK,
144     LDAP_THREADID_LOCK,
145 #ifdef LDAP_SASLIO_HOOKS
146     LDAP_SASL_LOCK,
147 #endif
148     LDAP_MAX_LOCK
149 } LDAPLock;
150 
151 /*
152  * This structure represents both ldap messages and ldap responses.
153  * These are really the same, except in the case of search responses,
154  * where a response has multiple messages.
155  */
156 
157 struct ldapmsg {
158 	int		lm_msgid;	/* the message id */
159 	int		lm_msgtype;	/* the message type */
160 	BerElement	*lm_ber;	/* the ber encoded message contents */
161 	struct ldapmsg	*lm_chain;	/* for search - next msg in the resp */
162 	struct ldapmsg	*lm_next;	/* next response */
163 	int		lm_fromcache;	/* memcache: origin of message */
164 };
165 
166 /*
167  * structure for tracking LDAP server host, ports, DNs, etc.
168  */
169 typedef struct ldap_server {
170 	char			*lsrv_host;
171 	char			*lsrv_dn;	/* if NULL, use default */
172 	int			lsrv_port;
173 	unsigned long		lsrv_options;	/* boolean options */
174 #define LDAP_SRV_OPT_SECURE	0x01
175 	struct ldap_server	*lsrv_next;
176 } LDAPServer;
177 
178 /*
179  * structure for representing an LDAP server connection
180  */
181 typedef struct ldap_conn {
182 	Sockbuf			*lconn_sb;
183 	BerElement		*lconn_ber;  /* non-NULL if in midst of msg. */
184 	int			lconn_version;	/* LDAP protocol version */
185 	int			lconn_refcnt;
186 	unsigned long		lconn_lastused;	/* time */
187 	int			lconn_status;
188 #define LDAP_CONNST_NEEDSOCKET		1
189 #define LDAP_CONNST_CONNECTING		2
190 #define LDAP_CONNST_CONNECTED		3
191 #define LDAP_CONNST_DEAD		4
192 	LDAPServer		*lconn_server;
193 	char			*lconn_binddn;	/* DN of last successful bind */
194 	int			lconn_bound;	/* has a bind been done? */
195 	char			*lconn_krbinstance;
196 	struct ldap_conn	*lconn_next;
197 } LDAPConn;
198 
199 
200 /*
201  * structure used to track outstanding requests
202  */
203 typedef struct ldapreq {
204 	int		lr_msgid;	/* the message id */
205 	int		lr_status;	/* status of request */
206 #define LDAP_REQST_INPROGRESS	1
207 #define LDAP_REQST_CHASINGREFS	2
208 #define LDAP_REQST_NOTCONNECTED	3
209 #define LDAP_REQST_WRITING	4
210 #define LDAP_REQST_CONNDEAD	5	/* associated conn. has failed */
211 	int		lr_outrefcnt;	/* count of outstanding referrals */
212 	int		lr_origid;	/* original request's message id */
213 	int		lr_parentcnt;	/* count of parent requests */
214 	int		lr_res_msgtype;	/* result message type */
215 	int		lr_res_errno;	/* result LDAP errno */
216 	char		*lr_res_error;	/* result error string */
217 	char		*lr_res_matched;/* result matched DN string */
218 	BerElement	*lr_ber;	/* ber encoded request contents */
219 	LDAPConn	*lr_conn;	/* connection used to send request */
220 	char		*lr_binddn;	/* request is a bind for this DN */
221 	struct ldapreq	*lr_parent;	/* request that spawned this referral */
222 	struct ldapreq	*lr_child;	/* list of requests we spawned */
223 	struct ldapreq	*lr_sibling;	/* next referral spawned */
224 	struct ldapreq	*lr_prev;	/* ld->ld_requests previous request */
225 	struct ldapreq	*lr_next;	/* ld->ld_requests next request */
226 } LDAPRequest;
227 
228 typedef struct ldappend {
229 	void		*lp_sema;	/* semaphore to post */
230 	int		lp_msgid;	/* message id */
231 	LDAPMessage	*lp_result;	/* result storage */
232 	struct ldappend	*lp_prev;	/* previous pending */
233 	struct ldappend	*lp_next;	/* next pending */
234 } LDAPPend;
235 
236 /*
237  * forward declaration for I/O status structure (defined in os-ip.c)
238  */
239 typedef struct nsldapi_iostatus_info NSLDAPIIOStatus;
240 
241 /*
242  * old extended IO structure (before writev callback was added)
243  */
244 struct ldap_x_ext_io_fns_rev0 {
245         int                                     lextiof_size;
246         LDAP_X_EXTIOF_CONNECT_CALLBACK          *lextiof_connect;
247         LDAP_X_EXTIOF_CLOSE_CALLBACK            *lextiof_close;
248         LDAP_X_EXTIOF_READ_CALLBACK             *lextiof_read;
249         LDAP_X_EXTIOF_WRITE_CALLBACK            *lextiof_write;
250         LDAP_X_EXTIOF_POLL_CALLBACK             *lextiof_poll;
251         LDAP_X_EXTIOF_NEWHANDLE_CALLBACK        *lextiof_newhandle;
252         LDAP_X_EXTIOF_DISPOSEHANDLE_CALLBACK    *lextiof_disposehandle;
253         void                                    *lextiof_session_arg;
254 };
255 #define LDAP_X_EXTIO_FNS_SIZE_REV0   sizeof(struct ldap_x_ext_io_fns_rev0)
256 
257 /*
258  * structure representing an ldap connection
259  */
260 struct ldap {
261 	struct sockbuf	*ld_sbp;	/* pointer to socket desc. & buffer */
262 	char		*ld_host;
263 	int		ld_version;	/* LDAP protocol version */
264 	char		ld_lberoptions;
265 	int		ld_deref;
266 
267 	int		ld_timelimit;
268 	int		ld_sizelimit;
269 
270 	struct ldap_filt_desc	*ld_filtd;	/* from getfilter for ufn searches */
271 	char		*ld_ufnprefix;	/* for incomplete ufn's */
272 
273 	int		ld_errno;
274 	char		*ld_error;
275 	char		*ld_matched;
276 	int		ld_msgid;
277 
278 	/* do not mess with these */
279 	LDAPRequest	*ld_requests;	/* list of outstanding requests */
280 	LDAPMessage	*ld_responses;	/* list of outstanding responses */
281 	int		*ld_abandoned;	/* array of abandoned requests */
282 	char		*ld_cldapdn;	/* DN used in connectionless search */
283 
284 	/* it is OK to change these next four values directly */
285 	int		ld_cldaptries;	/* connectionless search retry count */
286 	int		ld_cldaptimeout;/* time between retries */
287 	int		ld_refhoplimit;	/* limit on referral nesting */
288 	unsigned long	ld_options;	/* boolean options */
289 
290 #define LDAP_BITOPT_REFERRALS	0x80000000
291 #define LDAP_BITOPT_SSL		0x40000000
292 #define LDAP_BITOPT_DNS		0x20000000
293 #define LDAP_BITOPT_RESTART	0x10000000
294 #define LDAP_BITOPT_RECONNECT	0x08000000
295 #define LDAP_BITOPT_ASYNC       0x04000000
296 
297 	/* do not mess with the rest though */
298 	char		*ld_defhost;	/* full name of default server */
299 	int		ld_defport;	/* port of default server */
300 	BERTranslateProc ld_lber_encode_translate_proc;
301 	BERTranslateProc ld_lber_decode_translate_proc;
302 	LDAPConn	*ld_defconn;	/* default connection */
303 	LDAPConn	*ld_conns;	/* list of all server connections */
304 	NSLDAPIIOStatus	*ld_iostatus;	/* status info. about network sockets */
305 	LDAP_REBINDPROC_CALLBACK *ld_rebind_fn;
306 	void		*ld_rebind_arg;
307 
308 	/* function pointers, etc. for extended I/O */
309 	struct ldap_x_ext_io_fns ld_ext_io_fns;
310 #define ld_extio_size		ld_ext_io_fns.lextiof_size
311 #define ld_extclose_fn		ld_ext_io_fns.lextiof_close
312 #define ld_extconnect_fn	ld_ext_io_fns.lextiof_connect
313 #define ld_extread_fn		ld_ext_io_fns.lextiof_read
314 #define ld_extwrite_fn		ld_ext_io_fns.lextiof_write
315 #define ld_extwritev_fn		ld_ext_io_fns.lextiof_writev
316 #define ld_extpoll_fn		ld_ext_io_fns.lextiof_poll
317 #define ld_extnewhandle_fn	ld_ext_io_fns.lextiof_newhandle
318 #define ld_extdisposehandle_fn	ld_ext_io_fns.lextiof_disposehandle
319 #define ld_ext_session_arg	ld_ext_io_fns.lextiof_session_arg
320 
321 	/* allocated pointer for older I/O functions */
322 	struct ldap_io_fns	*ld_io_fns_ptr;
323 #define NSLDAPI_USING_CLASSIC_IO_FUNCTIONS( ld ) ((ld)->ld_io_fns_ptr != NULL)
324 
325 	/* function pointers, etc. for DNS */
326 	struct ldap_dns_fns	ld_dnsfn;
327 #define ld_dns_extradata	ld_dnsfn.lddnsfn_extradata
328 #define ld_dns_bufsize		ld_dnsfn.lddnsfn_bufsize
329 #define ld_dns_gethostbyname_fn	ld_dnsfn.lddnsfn_gethostbyname
330 #define ld_dns_gethostbyaddr_fn	ld_dnsfn.lddnsfn_gethostbyaddr
331 #define ld_dns_getpeername_fn	ld_dnsfn.lddnsfn_getpeername
332 
333 	/* function pointers, etc. for threading */
334 	struct ldap_thread_fns	ld_thread;
335 #define ld_mutex_alloc_fn	ld_thread.ltf_mutex_alloc
336 #define ld_mutex_free_fn	ld_thread.ltf_mutex_free
337 #define ld_mutex_lock_fn	ld_thread.ltf_mutex_lock
338 #define ld_mutex_unlock_fn	ld_thread.ltf_mutex_unlock
339 #define ld_get_errno_fn		ld_thread.ltf_get_errno
340 #define ld_set_errno_fn		ld_thread.ltf_set_errno
341 #define ld_get_lderrno_fn	ld_thread.ltf_get_lderrno
342 #define ld_set_lderrno_fn	ld_thread.ltf_set_lderrno
343 #define ld_lderrno_arg		ld_thread.ltf_lderrno_arg
344 	void			**ld_mutex;
345 
346 	/* function pointers, etc. for caching */
347 	int			ld_cache_on;
348 	int			ld_cache_strategy;
349 	struct ldap_cache_fns	ld_cache;
350 #define ld_cache_config		ld_cache.lcf_config
351 #define ld_cache_bind		ld_cache.lcf_bind
352 #define ld_cache_unbind		ld_cache.lcf_unbind
353 #define ld_cache_search		ld_cache.lcf_search
354 #define ld_cache_compare	ld_cache.lcf_compare
355 #define ld_cache_add		ld_cache.lcf_add
356 #define ld_cache_delete		ld_cache.lcf_delete
357 #if 0
358 #define ld_cache_rename		ld_cache.lcf_rename
359 #endif
360 #define ld_cache_modify		ld_cache.lcf_modify
361 #define ld_cache_modrdn		ld_cache.lcf_modrdn
362 #define ld_cache_abandon	ld_cache.lcf_abandon
363 #define ld_cache_result		ld_cache.lcf_result
364 #define ld_cache_flush		ld_cache.lcf_flush
365 #define ld_cache_arg		ld_cache.lcf_arg
366 
367 	/* ldapv3 controls */
368 	LDAPControl		**ld_servercontrols;
369 	LDAPControl		**ld_clientcontrols;
370 
371 	/* Preferred language */
372 	char            *ld_preferred_language;
373 
374 	/* MemCache */
375 	LDAPMemCache	*ld_memcache;
376 
377 	/* Pending results */
378 	LDAPPend	*ld_pend;	/* list of pending results */
379 
380 	/* extra thread function pointers */
381 	struct ldap_extra_thread_fns	ld_thread2;
382 
383 	/* With the 4.0 version of the LDAP SDK */
384 	/* the extra thread functions except for */
385 	/* the ld_threadid_fn has been disabled */
386 	/* Look at the release notes for the full */
387 	/* explanation */
388 #define ld_mutex_trylock_fn		ld_thread2.ltf_mutex_trylock
389 #define ld_sema_alloc_fn		ld_thread2.ltf_sema_alloc
390 #define ld_sema_free_fn			ld_thread2.ltf_sema_free
391 #define ld_sema_wait_fn			ld_thread2.ltf_sema_wait
392 #define ld_sema_post_fn			ld_thread2.ltf_sema_post
393 #define ld_threadid_fn			ld_thread2.ltf_threadid_fn
394 
395 	/* extra data for mutex handling in referrals */
396 	void 			*ld_mutex_threadid[LDAP_MAX_LOCK];
397 	unsigned long		ld_mutex_refcnt[LDAP_MAX_LOCK];
398 
399 	/* connect timeout value (milliseconds) */
400 	int				ld_connect_timeout;
401 
402 #ifdef LDAP_SASLIO_HOOKS
403 	/* SASL default option settings */
404 	char			*ld_def_sasl_mech;
405 	char			*ld_def_sasl_realm;
406 	char			*ld_def_sasl_authcid;
407 	char			*ld_def_sasl_authzid;
408 	/* SASL Security properties */
409 	struct sasl_security_properties ld_sasl_secprops;
410 	/* prldap shadow io functions */
411 	struct ldap_x_ext_io_fns ld_sasl_io_fns;
412 #endif
413 };
414 
415 /* allocate/free mutex */
416 #define LDAP_MUTEX_ALLOC( ld ) \
417 	(((ld)->ld_mutex_alloc_fn != NULL) ? (ld)->ld_mutex_alloc_fn() : NULL)
418 
419 /* allocate/free mutex */
420 #define LDAP_MUTEX_FREE( ld, m ) \
421 	if ( (ld)->ld_mutex_free_fn != NULL && m != NULL ) { \
422 		(ld)->ld_mutex_free_fn( m ); \
423 	}
424 
425 /* enter/exit critical sections */
426 /*
427  * The locks assume that the locks are thread safe.  XXXmcs: which means???
428  *
429  * Note that we test for both ld_mutex_lock_fn != NULL AND ld_mutex != NULL.
430  * This is necessary because there is a window in ldap_init() between the
431  * time we set the ld_mutex_lock_fn pointer and the time we allocate the
432  * mutexes in which external code COULD be called which COULD make a call to
433  * something like ldap_get_option(), which uses LDAP_MUTEX_LOCK().  The
434  * libprldap code does this in its newhandle callback (prldap_newhandle).
435  */
436 
437 #define LDAP_MUTEX_LOCK(ld, lock) \
438     if ((ld)->ld_mutex_lock_fn != NULL && ld->ld_mutex != NULL) { \
439         if ((ld)->ld_threadid_fn != NULL) { \
440             if ((ld)->ld_mutex_threadid[lock] == (ld)->ld_threadid_fn()) { \
441                 (ld)->ld_mutex_refcnt[lock]++; \
442             } else { \
443                 (ld)->ld_mutex_lock_fn(ld->ld_mutex[lock]); \
444                 (ld)->ld_mutex_threadid[lock] = ld->ld_threadid_fn(); \
445                 (ld)->ld_mutex_refcnt[lock] = 1; \
446             } \
447         } else { \
448             (ld)->ld_mutex_lock_fn(ld->ld_mutex[lock]); \
449         } \
450     }
451 
452 #define LDAP_MUTEX_UNLOCK(ld, lock) \
453     if ((ld)->ld_mutex_lock_fn != NULL && ld->ld_mutex != NULL) { \
454         if ((ld)->ld_threadid_fn != NULL) { \
455             if ((ld)->ld_mutex_threadid[lock] == (ld)->ld_threadid_fn()) { \
456                 (ld)->ld_mutex_refcnt[lock]--; \
457                 if ((ld)->ld_mutex_refcnt[lock] <= 0) { \
458                     (ld)->ld_mutex_threadid[lock] = (void *) -1; \
459                     (ld)->ld_mutex_refcnt[lock] = 0; \
460                     (ld)->ld_mutex_unlock_fn(ld->ld_mutex[lock]); \
461                 } \
462             } \
463         } else { \
464             ld->ld_mutex_unlock_fn(ld->ld_mutex[lock]); \
465         } \
466     }
467 
468 /* Backward compatibility locks */
469 #define LDAP_MUTEX_BC_LOCK( ld, i ) \
470 	/* the ld_mutex_trylock_fn is always set to NULL */ \
471 	/* in setoption.c as the extra thread functions were */ \
472 	/* turned off in the 4.0 SDK.  This check will  */ \
473 	/* always be true */ \
474 	if( (ld)->ld_mutex_trylock_fn == NULL ) { \
475 		LDAP_MUTEX_LOCK( ld, i ) ; \
476 	}
477 #define LDAP_MUTEX_BC_UNLOCK( ld, i ) \
478 	/* the ld_mutex_trylock_fn is always set to NULL */ \
479 	/* in setoption.c as the extra thread functions were */ \
480 	/* turned off in the 4.0 SDK.  This check will  */ \
481 	/* always be true */ \
482 	if( (ld)->ld_mutex_trylock_fn == NULL ) { \
483 		LDAP_MUTEX_UNLOCK( ld, i ) ; \
484 	}
485 
486 /* allocate/free semaphore */
487 #define LDAP_SEMA_ALLOC( ld ) \
488 	(((ld)->ld_sema_alloc_fn != NULL) ? (ld)->ld_sema_alloc_fn() : NULL)
489 #define LDAP_SEMA_FREE( ld, m ) \
490 	if ( (ld)->ld_sema_free_fn != NULL && m != NULL ) { \
491 		(ld)->ld_sema_free_fn( m ); \
492 	}
493 
494 /* wait/post binary semaphore */
495 #define LDAP_SEMA_WAIT( ld, lp ) \
496 	if ( (ld)->ld_sema_wait_fn != NULL ) { \
497 		(ld)->ld_sema_wait_fn( lp->lp_sema ); \
498 	}
499 #define LDAP_SEMA_POST( ld, lp ) \
500 	if ( (ld)->ld_sema_post_fn != NULL ) { \
501 		(ld)->ld_sema_post_fn( lp->lp_sema ); \
502 	}
503 #define POST( ld, y, z ) \
504 	/* the ld_mutex_trylock_fn is always set to NULL */ \
505 	/* in setoption.c as the extra thread functions were */ \
506 	/* turned off in the 4.0 SDK.  This check will  */ \
507 	/* always be false */ \
508 	if( (ld)->ld_mutex_trylock_fn != NULL ) { \
509 		nsldapi_post_result( ld, y, z ); \
510 	}
511 
512 /* get/set errno */
513 #ifndef macintosh
514 #define LDAP_SET_ERRNO( ld, e ) \
515 	if ( (ld)->ld_set_errno_fn != NULL ) { \
516 		(ld)->ld_set_errno_fn( e ); \
517 	} else { \
518 		errno = e; \
519 	}
520 #define LDAP_GET_ERRNO( ld ) \
521 	(((ld)->ld_get_errno_fn != NULL) ? \
522 		(ld)->ld_get_errno_fn() : errno)
523 #else /* macintosh */
524 #define LDAP_SET_ERRNO( ld, e ) \
525 	if ( (ld)->ld_set_errno_fn != NULL ) { \
526 		(ld)->ld_set_errno_fn( e ); \
527 	}
528 #define LDAP_GET_ERRNO( ld ) \
529 	(((ld)->ld_get_errno_fn != NULL) ? \
530 		(ld)->ld_get_errno_fn() : 0)
531 #endif
532 
533 
534 /* get/set ldap-specific errno */
535 #define LDAP_SET_LDERRNO( ld, e, m, s )	ldap_set_lderrno( ld, e, m, s )
536 #define LDAP_GET_LDERRNO( ld, m, s ) ldap_get_lderrno( ld, m, s )
537 
538 /*
539  * your standard "mimimum of two values" macro
540  */
541 #define NSLDAPI_MIN(a, b)	(((a) < (b)) ? (a) : (b))
542 
543 /*
544  * handy macro to check whether LDAP struct is set up for CLDAP or not
545  */
546 #define LDAP_IS_CLDAP( ld )	( ld->ld_sbp->sb_naddr > 0 )
547 
548 /*
549  * handy macro to check errno "e" for an "in progress" sort of error
550  */
551 #if defined(macintosh) || defined(_WINDOWS)
552 #define NSLDAPI_ERRNO_IO_INPROGRESS( e )  ((e) == EWOULDBLOCK || (e) == EAGAIN)
553 #else
554 #ifdef EAGAIN
555 #define NSLDAPI_ERRNO_IO_INPROGRESS( e )  ((e) == EWOULDBLOCK || (e) == EINPROGRESS || (e) == EAGAIN)
556 #else /* EAGAIN */
557 #define NSLDAPI_ERRNO_IO_INPROGRESS( e )  ((e) == EWOULDBLOCK || (e) == EINPROGRESS)
558 #endif /* EAGAIN */
559 #endif /* macintosh || _WINDOWS*/
560 
561 /*
562  * macro to return the LDAP protocol version we are using
563  */
564 #define NSLDAPI_LDAP_VERSION( ld )	( (ld)->ld_defconn == NULL ? \
565 					(ld)->ld_version : \
566 					(ld)->ld_defconn->lconn_version )
567 
568 /*
569  * Structures used for handling client filter lists.
570  */
571 #define LDAP_FILT_MAXSIZ	1024
572 
573 struct ldap_filt_list {
574     char			*lfl_tag;
575     char			*lfl_pattern;
576     char			*lfl_delims;
577     struct ldap_filt_info	*lfl_ilist;
578     struct ldap_filt_list	*lfl_next;
579 };
580 
581 struct ldap_filt_desc {
582 	LDAPFiltList		*lfd_filtlist;
583 	LDAPFiltInfo		*lfd_curfip;
584 	LDAPFiltInfo		lfd_retfi;
585 	char			lfd_filter[ LDAP_FILT_MAXSIZ ];
586 	char			*lfd_curval;
587 	char			*lfd_curvalcopy;
588 	char			**lfd_curvalwords;
589 	char			*lfd_filtprefix;
590 	char			*lfd_filtsuffix;
591 };
592 
593 /*
594  * "internal" globals used to track defaults and memory allocation callbacks:
595  *    (the actual definitions are in open.c)
596  */
597 extern struct ldap			nsldapi_ld_defaults;
598 extern struct ldap_memalloc_fns		nsldapi_memalloc_fns;
599 extern int				nsldapi_initialized;
600 
601 
602 /*
603  * Memory allocation done in liblber should all go through one of the
604  * following macros. This is so we can plug-in alternative memory
605  * allocators, etc. as the need arises.
606  */
607 #define NSLDAPI_MALLOC( size )		ldap_x_malloc( size )
608 #define NSLDAPI_CALLOC( nelem, elsize )	ldap_x_calloc( nelem, elsize )
609 #define NSLDAPI_REALLOC( ptr, size )	ldap_x_realloc( ptr, size )
610 #define NSLDAPI_FREE( ptr )		ldap_x_free( ptr )
611 
612 
613 /*
614  * macros used to check validity of data structures and parameters
615  */
616 #define NSLDAPI_VALID_LDAP_POINTER( ld ) \
617 	( (ld) != NULL )
618 
619 #define NSLDAPI_VALID_LDAPMESSAGE_POINTER( lm ) \
620 	( (lm) != NULL )
621 
622 #define NSLDAPI_VALID_LDAPMESSAGE_ENTRY_POINTER( lm ) \
623 	( (lm) != NULL && (lm)->lm_msgtype == LDAP_RES_SEARCH_ENTRY )
624 
625 #define NSLDAPI_VALID_LDAPMESSAGE_REFERENCE_POINTER( lm ) \
626 	( (lm) != NULL && (lm)->lm_msgtype == LDAP_RES_SEARCH_REFERENCE )
627 
628 #define NSLDAPI_VALID_LDAPMESSAGE_BINDRESULT_POINTER( lm ) \
629 	( (lm) != NULL && (lm)->lm_msgtype == LDAP_RES_BIND )
630 
631 #define NSLDAPI_VALID_LDAPMESSAGE_EXRESULT_POINTER( lm ) \
632 	( (lm) != NULL && (lm)->lm_msgtype == LDAP_RES_EXTENDED )
633 
634 #define NSLDAPI_VALID_LDAPMOD_ARRAY( mods ) \
635 	( (mods) != NULL )
636 
637 #define NSLDAPI_VALID_NONEMPTY_LDAPMOD_ARRAY( mods ) \
638 	( (mods) != NULL && (mods)[0] != NULL )
639 
640 #define NSLDAPI_IS_SEARCH_ENTRY( code ) \
641 	((code) == LDAP_RES_SEARCH_ENTRY)
642 
643 #define NSLDAPI_IS_SEARCH_RESULT( code ) \
644 	((code) == LDAP_RES_SEARCH_RESULT)
645 
646 #define NSLDAPI_SEARCH_RELATED_RESULT( code ) \
647 	(NSLDAPI_IS_SEARCH_RESULT( code ) || NSLDAPI_IS_SEARCH_ENTRY( code ))
648 
649 /*
650  * in bind.c
651  */
652 char *nsldapi_get_binddn( LDAP *ld );
653 
654 /*
655  * in cache.c
656  */
657 void nsldapi_add_result_to_cache( LDAP *ld, LDAPMessage *result );
658 
659 /*
660  * in dsparse.c
661  */
662 int ldap_next_line_tokens( char **bufp, long *blenp, char ***toksp );
663 void ldap_free_strarray( char **sap );
664 
665 /*
666  * in error.c
667  */
668 int nsldapi_parse_result( LDAP *ld, int msgtype, BerElement *rber,
669     int *errcodep, char **matchednp, char **errmsgp, char ***referralsp,
670     LDAPControl ***serverctrlsp );
671 
672 /*
673  * in open.c
674  */
675 void nsldapi_initialize_defaults( void );
676 void nsldapi_mutex_alloc_all( LDAP *ld );
677 void nsldapi_mutex_free_all( LDAP *ld );
678 int nsldapi_open_ldap_defconn( LDAP *ld );
679 char *nsldapi_strdup( const char *s );  /* if s is NULL, returns NULL */
680 
681 /*
682  * in os-ip.c
683  */
684 int nsldapi_connect_to_host( LDAP *ld, Sockbuf *sb, const char *host,
685 	int port, int secure, char **krbinstancep );
686 void nsldapi_close_connection( LDAP *ld, Sockbuf *sb );
687 
688 int nsldapi_iostatus_poll( LDAP *ld, struct timeval *timeout );
689 void nsldapi_iostatus_free( LDAP *ld );
690 int nsldapi_iostatus_interest_write( LDAP *ld, Sockbuf *sb );
691 int nsldapi_iostatus_interest_read( LDAP *ld, Sockbuf *sb );
692 int nsldapi_iostatus_interest_clear( LDAP *ld, Sockbuf *sb );
693 int nsldapi_iostatus_is_read_ready( LDAP *ld, Sockbuf *sb );
694 int nsldapi_iostatus_is_write_ready( LDAP *ld, Sockbuf *sb );
695 int nsldapi_install_lber_extiofns( LDAP *ld, Sockbuf *sb );
696 int nsldapi_install_compat_io_fns( LDAP *ld, struct ldap_io_fns *iofns );
697 
698 /*
699  * if referral.c
700  */
701 int nsldapi_parse_reference( LDAP *ld, BerElement *rber, char ***referralsp,
702 	LDAPControl ***serverctrlsp );
703 
704 /*
705  * in result.c
706  */
707 int ldap_msgdelete( LDAP *ld, int msgid );
708 int nsldapi_result_nolock( LDAP *ld, int msgid, int all, int unlock_permitted,
709     struct timeval *timeout, LDAPMessage **result );
710 int nsldapi_wait_result( LDAP *ld, int msgid, int all, struct timeval *timeout,
711     LDAPMessage **result );
712 int nsldapi_post_result( LDAP *ld, int msgid, LDAPMessage *result );
713 
714 /*
715  * in request.c
716  */
717 int nsldapi_send_initial_request( LDAP *ld, int msgid, unsigned long msgtype,
718 	char *dn, BerElement *ber );
719 int nsldapi_alloc_ber_with_options( LDAP *ld, BerElement **berp );
720 void nsldapi_set_ber_options( LDAP *ld, BerElement *ber );
721 int nsldapi_ber_flush( LDAP *ld, Sockbuf *sb, BerElement *ber, int freeit,
722 	int async );
723 int nsldapi_send_server_request( LDAP *ld, BerElement *ber, int msgid,
724 	LDAPRequest *parentreq, LDAPServer *srvlist, LDAPConn *lc,
725 	char *bindreqdn, int bind );
726 LDAPConn *nsldapi_new_connection( LDAP *ld, LDAPServer **srvlistp, int use_ldsb,
727 	int connect, int bind );
728 LDAPRequest *nsldapi_find_request_by_msgid( LDAP *ld, int msgid );
729 void nsldapi_free_request( LDAP *ld, LDAPRequest *lr, int free_conn );
730 void nsldapi_free_connection( LDAP *ld, LDAPConn *lc,
731 	LDAPControl **serverctrls, LDAPControl **clientctrls,
732 	int force, int unbind );
733 void nsldapi_dump_connection( LDAP *ld, LDAPConn *lconns, int all );
734 void nsldapi_dump_requests_and_responses( LDAP *ld );
735 int nsldapi_chase_v2_referrals( LDAP *ld, LDAPRequest *lr, char **errstrp,
736 	int *totalcountp, int *chasingcountp );
737 int nsldapi_chase_v3_refs( LDAP *ld, LDAPRequest *lr, char **refs,
738 	int is_reference, int *totalcountp, int *chasingcountp );
739 int nsldapi_append_referral( LDAP *ld, char **referralsp, char *s );
740 void nsldapi_connection_lost_nolock( LDAP *ld, Sockbuf *sb );
741 
742 /*
743  * in search.c
744  */
745 int nsldapi_build_search_req( LDAP *ld, const char *base, int scope,
746 	const char *filter, char **attrs, int attrsonly,
747 	LDAPControl **serverctrls, LDAPControl **clientctrls,
748 	int timelimit, int sizelimit, int msgid, BerElement **berp );
749 
750 int ldap_put_filter( BerElement *ber, char *str );
751 /*
752  * in unbind.c
753  */
754 int ldap_ld_free( LDAP *ld, LDAPControl **serverctrls,
755 	LDAPControl **clientctrls, int close );
756 int nsldapi_send_unbind( LDAP *ld, Sockbuf *sb, LDAPControl **serverctrls,
757 	LDAPControl **clientctrls );
758 
759 #ifdef LDAP_DNS
760 /*
761  * in getdxbyname.c
762  */
763 char **nsldapi_getdxbyname( char *domain );
764 
765 #endif /* LDAP_DNS */
766 
767 /*
768  * in unescape.c
769  */
770 void nsldapi_hex_unescape( char *s );
771 
772 /*
773  * in reslist.c
774  */
775 LDAPMessage *ldap_delete_result_entry( LDAPMessage **list, LDAPMessage *e );
776 void ldap_add_result_entry( LDAPMessage **list, LDAPMessage *e );
777 
778 /*
779  * in compat.c
780  */
781 #ifdef hpux
782 char *nsldapi_compat_ctime_r( const time_t *clock, char *buf, int buflen );
783 struct hostent *nsldapi_compat_gethostbyname_r( const char *name,
784 	struct hostent *result, char *buffer, int buflen, int *h_errnop );
785 #endif /* hpux */
786 
787 /*
788  * in control.c
789  */
790 int nsldapi_put_controls( LDAP *ld, LDAPControl **ctrls, int closeseq,
791 	BerElement *ber );
792 int nsldapi_get_controls( BerElement *ber, LDAPControl ***controlsp );
793 int nsldapi_dup_controls( LDAP *ld, LDAPControl ***ldctrls,
794 	LDAPControl **newctrls );
795 int nsldapi_build_control( char *oid, BerElement *ber, int freeber,
796     char iscritical, LDAPControl **ctrlp );
797 
798 
799 /*
800  * in url.c
801  */
802 int nsldapi_url_parse( const char *inurl, LDAPURLDesc **ludpp,
803 	int dn_required );
804 
805 /*
806  * in ../ber/bprint.c
807  */
808 void ber_err_print( char *data );
809 
810 #ifdef _SOLARIS_SDK
811 /*
812  * in ../prldap/ldappr-dns.c
813  */
814 int  prldap_x_install_dns_skipdb(LDAP *ld, const char *skip);
815 /*
816  * in ../prldap/ldappr-threads.c
817  */
818 void prldap_nspr_init(void);
819 #endif
820 
821 /*
822  * in ../prldap/ldappr-public.c
823  */
824 int
825 prldap_install_io_functions( LDAP *ld, int shared );
826 int
827 prldap_install_dns_functions( LDAP *ld );
828 int
829 prldap_install_thread_functions( LDAP *ld, int shared );
830 
831 
832 
833 #ifndef _SOLARIS_SDK
834 
835 /*
836  * in charset.c
837  *
838  * If we ever want to expose character set translation functionality to
839  * users of libldap, all of these prototypes will need to be moved to ldap.h
840  *
841  * These are moved to ldap.h in the Solaris version of the library
842  *
843  */
844 #ifdef STR_TRANSLATION
845 void ldap_set_string_translators( LDAP *ld,
846         BERTranslateProc encode_proc, BERTranslateProc decode_proc );
847 int ldap_translate_from_t61( LDAP *ld, char **bufp,
848         unsigned long *lenp, int free_input );
849 int ldap_translate_to_t61( LDAP *ld, char **bufp,
850         unsigned long *lenp, int free_input );
851 void ldap_enable_translation( LDAP *ld, LDAPMessage *entry,
852         int enable );
853 #ifdef LDAP_CHARSET_8859
854 int ldap_t61_to_8859( char **bufp, unsigned long *buflenp,
855         int free_input );
856 int ldap_8859_to_t61( char **bufp, unsigned long *buflenp,
857         int free_input );
858 #endif /* LDAP_CHARSET_8859 */
859 #endif /* STR_TRANSLATION */
860 
861 #endif /* _SOLARIS_SDK */
862 
863 /*
864  * in memcache.h
865  */
866 int ldap_memcache_createkey( LDAP *ld, const char *base, int scope,
867 	const char *filter, char **attrs, int attrsonly,
868 	LDAPControl **serverctrls, LDAPControl **clientctrls,
869 	unsigned long *keyp );
870 int ldap_memcache_result( LDAP *ld, int msgid, unsigned long key );
871 int ldap_memcache_new( LDAP *ld, int msgid, unsigned long key,
872 	const char *basedn );
873 int ldap_memcache_append( LDAP *ld, int msgid, int bLast, LDAPMessage *result );
874 int ldap_memcache_abandon( LDAP *ld, int msgid );
875 
876 #endif /* _LDAPINT_H */
877