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