1 /*
2  * Copyright 2001-2002 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 /*
10  * The contents of this file are subject to the Netscape Public
11  * License Version 1.1 (the "License"); you may not use this file
12  * except in compliance with the License. You may obtain a copy of
13  * the License at http://www.mozilla.org/NPL/
14  *
15  * Software distributed under the License is distributed on an "AS
16  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
17  * implied. See the License for the specific language governing
18  * rights and limitations under the License.
19  *
20  * The Original Code is Mozilla Communicator client code, released
21  * March 31, 1998.
22  *
23  * The Initial Developer of the Original Code is Netscape
24  * Communications Corporation. Portions created by Netscape are
25  * Copyright (C) 1998-1999 Netscape Communications Corporation. All
26  * Rights Reserved.
27  *
28  * Contributor(s):
29  */
30 
31 /*
32  * Public interface for libprldap -- use NSPR (Netscape Portable Runtime)
33  * I/O, threads, etc. with libldap.
34  *
35  */
36 
37 #include "ldappr-int.h"
38 
39 
40 /*
41  * Function: prldap_init().
42  *
43  * Create a new LDAP session handle, but with NSPR I/O, threading, and DNS
44  * functions installed.
45  *
46  * Pass a non-zero value for the 'shared' parameter if you plan to use
47  * this LDAP * handle from more than one thread.
48  *
49  * prldap_init() returns an LDAP session handle (or NULL if an error occurs).
50  */
51 LDAP * LDAP_CALL
52 prldap_init( const char *defhost, int defport, int shared )
53 {
54     LDAP	*ld;
55 
56     if (( ld = ldap_init( defhost, defport )) != NULL ) {
57 	if ( prldap_install_routines( ld, shared ) != LDAP_SUCCESS ) {
58 	    prldap_set_system_errno( EINVAL );	/* XXXmcs: just a guess! */
59 	    ldap_unbind( ld );
60 	    ld = NULL;
61 	}
62     }
63 
64     return( ld );
65 }
66 
67 
68 /*
69  * Function: prldap_install_routines().
70  *
71  * Install NSPR I/O, threading, and DNS functions so they will be used by
72  * 'ld'.
73  *
74  * If 'ld' is NULL, the functions are installed as the default functions
75  * for all new LDAP * handles).
76  *
77  * Pass a non-zero value for the 'shared' parameter if you plan to use
78  * this LDAP * handle from more than one thread.
79  *
80  * prldap_install_routines() returns an LDAP API error code (LDAP_SUCCESS
81  * if all goes well).
82  */
83 int LDAP_CALL
84 prldap_install_routines( LDAP *ld, int shared )
85 {
86 
87     if ( prldap_install_io_functions( ld, shared ) != 0
88 		|| prldap_install_thread_functions( ld, shared ) != 0
89 		|| prldap_install_dns_functions( ld ) != 0 ) {
90 	return( ldap_get_lderrno( ld, NULL, NULL ));
91     }
92 
93     return( LDAP_SUCCESS );
94 }
95 
96 
97 #ifndef _SOLARIS_SDK	/* Not used, left in to stay in sync with iplanet */
98 /*
99  * Function: prldap_set_session_option().
100  *
101  * Given an LDAP session handle or a session argument such is passed to
102  * SOCKET, POLL, NEWHANDLE, or DISPOSEHANDLE extended I/O callbacks, set
103  * an option that affects the prldap layer.
104  *
105  * If 'ld' and 'session" are both NULL, the option is set as the default
106  * for all new prldap sessions.
107  *
108  * Returns an LDAP API error code (LDAP_SUCCESS if all goes well).
109  */
110 int LDAP_CALL
111 prldap_set_session_option( LDAP *ld, void *sessionarg, int option, ... )
112 {
113     int				rc = LDAP_SUCCESS;	/* optimistic */
114     PRLDAPIOSessionArg		*prsessp = NULL;
115     va_list			ap;
116 
117     if ( NULL != ld ) {
118 	if ( LDAP_SUCCESS !=
119 		( rc = prldap_session_arg_from_ld( ld, &prsessp ))) {
120 	    return( rc );
121 	}
122     } else if ( NULL != sessionarg ) {
123 	prsessp = (PRLDAPIOSessionArg *)sessionarg;
124     }
125 
126     va_start( ap, option );
127     switch ( option ) {
128     case PRLDAP_OPT_IO_MAX_TIMEOUT:
129 	rc = prldap_set_io_max_timeout( prsessp, va_arg( ap, int ));
130 	break;
131     default:
132 	rc = LDAP_PARAM_ERROR;
133     }
134     va_end( ap );
135 
136     return( rc );
137 }
138 
139 
140 /*
141  * Function: prldap_get_session_option().
142  *
143  * Given an LDAP session handle or a session argument such is passed to
144  * SOCKET, POLL, NEWHANDLE, or DISPOSEHANDLE extended I/O callbacks, retrieve
145  * the setting for an option that affects the prldap layer.
146  *
147  * If 'ld' and 'session" are both NULL, the default option value for all new
148  * new prldap sessions is retrieved.
149  *
150  * Returns an LDAP API error code (LDAP_SUCCESS if all goes well).
151  */
152 int LDAP_CALL prldap_get_session_option( LDAP *ld, void *sessionarg,
153         int option, ... )
154 {
155     int				rc = LDAP_SUCCESS;	/* optimistic */
156     PRLDAPIOSessionArg		*prsessp = NULL;
157     va_list			ap;
158 
159     if ( NULL != ld ) {
160 	if ( LDAP_SUCCESS !=
161 		( rc = prldap_session_arg_from_ld( ld, &prsessp ))) {
162 	    return( rc );
163 	}
164     } else if ( NULL != sessionarg ) {
165 	prsessp = (PRLDAPIOSessionArg *)sessionarg;
166     }
167 
168     va_start( ap, option );
169     switch ( option ) {
170     case PRLDAP_OPT_IO_MAX_TIMEOUT:
171 	rc = prldap_get_io_max_timeout( prsessp, va_arg( ap, int * ));
172 	break;
173     default:
174 	rc = LDAP_PARAM_ERROR;
175     }
176     va_end( ap );
177 
178     return( rc );
179 }
180 #endif	/* !_SOLARIS_SDK */
181 
182 
183 /*
184  * Function: prldap_set_session_info().
185  *
186  * Given an LDAP session handle, set some application-specific data.
187  *
188  * Returns an LDAP API error code (LDAP_SUCCESS if all goes well).
189  */
190 int LDAP_CALL
191 prldap_set_session_info( LDAP *ld, void *sessionarg, PRLDAPSessionInfo *seip )
192 {
193     int				rc;
194     PRLDAPIOSessionArg		*prsessp;
195 
196     if ( seip == NULL || PRLDAP_SESSIONINFO_SIZE != seip->seinfo_size ) {
197 	ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL );
198 	return( LDAP_PARAM_ERROR );
199     }
200 
201     if ( NULL != ld ) {
202 	if ( LDAP_SUCCESS !=
203 		( rc = prldap_session_arg_from_ld( ld, &prsessp ))) {
204 	    return( rc );
205 	}
206     } else if ( NULL != sessionarg ) {
207 	prsessp = (PRLDAPIOSessionArg *)sessionarg;
208     } else {
209 	ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL );
210 	return( LDAP_PARAM_ERROR );
211     }
212 
213     prsessp->prsess_appdata = seip->seinfo_appdata;
214     return( LDAP_SUCCESS );
215 }
216 
217 
218 /*
219  * Function: prldap_get_session_info().
220  *
221  * Given an LDAP session handle, retrieve some application-specific data.
222  *
223  * Returns an LDAP API error code (LDAP_SUCCESS if all goes well, in
224  * which case the fields in the structure that seip points to are filled in).
225  */
226 int LDAP_CALL
227 prldap_get_session_info( LDAP *ld, void *sessionarg, PRLDAPSessionInfo *seip )
228 {
229     int				rc;
230     PRLDAPIOSessionArg		*prsessp;
231 
232     if ( seip == NULL || PRLDAP_SESSIONINFO_SIZE != seip->seinfo_size ) {
233 	ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL );
234 	return( LDAP_PARAM_ERROR );
235     }
236 
237     if ( NULL != ld ) {
238 	if ( LDAP_SUCCESS !=
239 		( rc = prldap_session_arg_from_ld( ld, &prsessp ))) {
240 	    return( rc );
241 	}
242     } else if ( NULL != sessionarg ) {
243 	prsessp = (PRLDAPIOSessionArg *)sessionarg;
244     } else {
245 	ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL );
246 	return( LDAP_PARAM_ERROR );
247     }
248 
249     seip->seinfo_appdata = prsessp->prsess_appdata;
250     return( LDAP_SUCCESS );
251 }
252 
253 
254 /*
255  * Function: prldap_set_socket_info().
256  *
257  * Given an integer fd and a void * argument such as those passed to the
258  * extended I/O callback functions, set socket specific information.
259  *
260  * Returns an LDAP API error code (LDAP_SUCCESS if all goes well).
261  *
262  * Note: it is only safe to change soinfo_prfd from within the SOCKET
263  * extended I/O callback function.
264  */
265 int LDAP_CALL
266 prldap_set_socket_info( int fd, void *socketarg, PRLDAPSocketInfo *soip )
267 {
268     PRLDAPIOSocketArg	*prsockp;
269 
270     if ( NULL == socketarg || NULL == soip ||
271 		PRLDAP_SOCKETINFO_SIZE != soip->soinfo_size ) {
272 	return( LDAP_PARAM_ERROR );
273     }
274 
275     prsockp = (PRLDAPIOSocketArg *)socketarg;
276     prsockp->prsock_prfd = soip->soinfo_prfd;
277     prsockp->prsock_appdata = soip->soinfo_appdata;
278 
279     return( LDAP_SUCCESS );
280 }
281 
282 
283 /*
284  * Function: prldap_get_socket_info().
285  *
286  * Given an integer fd and a void * argument such as those passed to the
287  * extended I/O callback functions, retrieve socket specific information.
288  *
289  * Returns an LDAP API error code (LDAP_SUCCESS if all goes well, in
290  * which case the fields in the structure that soip points to are filled in).
291  */
292 int LDAP_CALL
293 prldap_get_socket_info( int fd, void *socketarg, PRLDAPSocketInfo *soip )
294 {
295     PRLDAPIOSocketArg	*prsockp;
296 
297     if ( NULL == socketarg || NULL == soip ||
298 		PRLDAP_SOCKETINFO_SIZE != soip->soinfo_size ) {
299 	return( LDAP_PARAM_ERROR );
300     }
301 
302     prsockp = (PRLDAPIOSocketArg *)socketarg;
303     soip->soinfo_prfd = prsockp->prsock_prfd;
304     soip->soinfo_appdata = prsockp->prsock_appdata;
305 
306     return( LDAP_SUCCESS );
307 }
308 
309 /*
310  * Function: prldap_get_default_socket_info().
311  *
312  * Given an LDAP session handle, retrieve socket specific information.
313  * If ld is NULL, LDAP_PARAM_ERROR is returned.
314  *
315  * Returns an LDAP API error code (LDAP_SUCCESS if all goes well, in
316  * which case the fields in the structure that soip points to are filled in).
317  */
318 int LDAP_CALL
319 prldap_get_default_socket_info( LDAP *ld, PRLDAPSocketInfo *soip )
320 {
321     int rc;
322     PRLDAPIOSocketArg *prsockp;
323 
324 
325     if ( NULL == soip || PRLDAP_SOCKETINFO_SIZE != soip->soinfo_size ) {
326         ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL );
327         return( LDAP_PARAM_ERROR );
328     }
329 
330     if ( NULL != ld ) {
331         if ( LDAP_SUCCESS !=
332                 ( rc = prldap_socket_arg_from_ld( ld, &prsockp ))) {
333             return( rc );
334         }
335     } else {
336         ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL );
337         return( LDAP_PARAM_ERROR );
338     }
339 
340     soip->soinfo_prfd = prsockp->prsock_prfd;
341     soip->soinfo_appdata = prsockp->prsock_appdata;
342 
343     return( LDAP_SUCCESS );
344 }
345 
346 
347 /*
348  * Function: prldap_set_default_socket_info().
349  *
350  * Given an LDAP session handle, set socket specific information.
351  * If ld is NULL, LDAP_PARAM_ERROR is returned.
352  *
353  * Returns an LDAP API error code (LDAP_SUCCESS if all goes well, in
354  * which case the fields in the structure that soip points to are filled in).
355  */
356 int LDAP_CALL
357 prldap_set_default_socket_info( LDAP *ld, PRLDAPSocketInfo *soip )
358 {
359     int rc;
360     PRLDAPIOSocketArg *prsockp;
361 
362 
363     if ( NULL == soip || PRLDAP_SOCKETINFO_SIZE != soip->soinfo_size ) {
364         ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL );
365         return( LDAP_PARAM_ERROR );
366     }
367 
368     if ( NULL != ld ) {
369         if ( LDAP_SUCCESS !=
370                 ( rc = prldap_socket_arg_from_ld( ld, &prsockp ))) {
371             return( rc );
372         }
373     } else {
374         ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL );
375         return( LDAP_PARAM_ERROR );
376     }
377 
378     prsockp->prsock_prfd = soip->soinfo_prfd;
379     prsockp->prsock_appdata = soip->soinfo_appdata;
380 
381     return( LDAP_SUCCESS );
382 }
383