1 /*
2  * Copyright 2006 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 /*
98  * Function: prldap_set_session_option().
99  *
100  * Given an LDAP session handle or a session argument such is passed to
101  * SOCKET, POLL, NEWHANDLE, or DISPOSEHANDLE extended I/O callbacks, set
102  * an option that affects the prldap layer.
103  *
104  * If 'ld' and 'session" are both NULL, the option is set as the default
105  * for all new prldap sessions.
106  *
107  * Returns an LDAP API error code (LDAP_SUCCESS if all goes well).
108  */
109 int LDAP_CALL
110 prldap_set_session_option( LDAP *ld, void *sessionarg, int option, ... )
111 {
112     int				rc = LDAP_SUCCESS;	/* optimistic */
113     PRLDAPIOSessionArg		*prsessp = NULL;
114     va_list			ap;
115 
116     if ( NULL != ld ) {
117 	if ( LDAP_SUCCESS !=
118 		( rc = prldap_session_arg_from_ld( ld, &prsessp ))) {
119 	    return( rc );
120 	}
121     } else if ( NULL != sessionarg ) {
122 	prsessp = (PRLDAPIOSessionArg *)sessionarg;
123     }
124 
125     va_start( ap, option );
126     switch ( option ) {
127     case PRLDAP_OPT_IO_MAX_TIMEOUT:
128 	rc = prldap_set_io_max_timeout( prsessp, va_arg( ap, int ));
129 	break;
130     default:
131 	rc = LDAP_PARAM_ERROR;
132     }
133     va_end( ap );
134 
135     return( rc );
136 }
137 
138 
139 /*
140  * Function: prldap_get_session_option().
141  *
142  * Given an LDAP session handle or a session argument such is passed to
143  * SOCKET, POLL, NEWHANDLE, or DISPOSEHANDLE extended I/O callbacks, retrieve
144  * the setting for an option that affects the prldap layer.
145  *
146  * If 'ld' and 'session" are both NULL, the default option value for all new
147  * new prldap sessions is retrieved.
148  *
149  * Returns an LDAP API error code (LDAP_SUCCESS if all goes well).
150  */
151 int LDAP_CALL prldap_get_session_option( LDAP *ld, void *sessionarg,
152         int option, ... )
153 {
154     int				rc = LDAP_SUCCESS;	/* optimistic */
155     PRLDAPIOSessionArg		*prsessp = NULL;
156     va_list			ap;
157 
158     if ( NULL != ld ) {
159 	if ( LDAP_SUCCESS !=
160 		( rc = prldap_session_arg_from_ld( ld, &prsessp ))) {
161 	    return( rc );
162 	}
163     } else if ( NULL != sessionarg ) {
164 	prsessp = (PRLDAPIOSessionArg *)sessionarg;
165     }
166 
167     va_start( ap, option );
168     switch ( option ) {
169     case PRLDAP_OPT_IO_MAX_TIMEOUT:
170 	rc = prldap_get_io_max_timeout( prsessp, va_arg( ap, int * ));
171 	break;
172     default:
173 	rc = LDAP_PARAM_ERROR;
174     }
175     va_end( ap );
176 
177     return( rc );
178 }
179 
180 
181 /*
182  * Function: prldap_set_session_info().
183  *
184  * Given an LDAP session handle, set some application-specific data.
185  *
186  * Returns an LDAP API error code (LDAP_SUCCESS if all goes well).
187  */
188 int LDAP_CALL
189 prldap_set_session_info( LDAP *ld, void *sessionarg, PRLDAPSessionInfo *seip )
190 {
191     int				rc;
192     PRLDAPIOSessionArg		*prsessp;
193 
194     if ( seip == NULL || PRLDAP_SESSIONINFO_SIZE != seip->seinfo_size ) {
195 	ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL );
196 	return( LDAP_PARAM_ERROR );
197     }
198 
199     if ( NULL != ld ) {
200 	if ( LDAP_SUCCESS !=
201 		( rc = prldap_session_arg_from_ld( ld, &prsessp ))) {
202 	    return( rc );
203 	}
204     } else if ( NULL != sessionarg ) {
205 	prsessp = (PRLDAPIOSessionArg *)sessionarg;
206     } else {
207 	ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL );
208 	return( LDAP_PARAM_ERROR );
209     }
210 
211     prsessp->prsess_appdata = seip->seinfo_appdata;
212     return( LDAP_SUCCESS );
213 }
214 
215 
216 /*
217  * Function: prldap_get_session_info().
218  *
219  * Given an LDAP session handle, retrieve some application-specific data.
220  *
221  * Returns an LDAP API error code (LDAP_SUCCESS if all goes well, in
222  * which case the fields in the structure that seip points to are filled in).
223  */
224 int LDAP_CALL
225 prldap_get_session_info( LDAP *ld, void *sessionarg, PRLDAPSessionInfo *seip )
226 {
227     int				rc;
228     PRLDAPIOSessionArg		*prsessp;
229 
230     if ( seip == NULL || PRLDAP_SESSIONINFO_SIZE != seip->seinfo_size ) {
231 	ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL );
232 	return( LDAP_PARAM_ERROR );
233     }
234 
235     if ( NULL != ld ) {
236 	if ( LDAP_SUCCESS !=
237 		( rc = prldap_session_arg_from_ld( ld, &prsessp ))) {
238 	    return( rc );
239 	}
240     } else if ( NULL != sessionarg ) {
241 	prsessp = (PRLDAPIOSessionArg *)sessionarg;
242     } else {
243 	ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL );
244 	return( LDAP_PARAM_ERROR );
245     }
246 
247     seip->seinfo_appdata = prsessp->prsess_appdata;
248     return( LDAP_SUCCESS );
249 }
250 
251 
252 /*
253  * Function: prldap_set_socket_info().
254  *
255  * Given an integer fd and a void * argument such as those passed to the
256  * extended I/O callback functions, set socket specific information.
257  *
258  * Returns an LDAP API error code (LDAP_SUCCESS if all goes well).
259  *
260  * Note: it is only safe to change soinfo_prfd from within the SOCKET
261  * extended I/O callback function.
262  */
263 int LDAP_CALL
264 prldap_set_socket_info( int fd, void *socketarg, PRLDAPSocketInfo *soip )
265 {
266     PRLDAPIOSocketArg	*prsockp;
267 
268     if ( NULL == socketarg || NULL == soip ||
269 		PRLDAP_SOCKETINFO_SIZE != soip->soinfo_size ) {
270 	return( LDAP_PARAM_ERROR );
271     }
272 
273     prsockp = (PRLDAPIOSocketArg *)socketarg;
274     prsockp->prsock_prfd = soip->soinfo_prfd;
275     prsockp->prsock_appdata = soip->soinfo_appdata;
276 
277     return( LDAP_SUCCESS );
278 }
279 
280 
281 /*
282  * Function: prldap_get_socket_info().
283  *
284  * Given an integer fd and a void * argument such as those passed to the
285  * extended I/O callback functions, retrieve socket specific information.
286  *
287  * Returns an LDAP API error code (LDAP_SUCCESS if all goes well, in
288  * which case the fields in the structure that soip points to are filled in).
289  */
290 int LDAP_CALL
291 prldap_get_socket_info( int fd, void *socketarg, PRLDAPSocketInfo *soip )
292 {
293     PRLDAPIOSocketArg	*prsockp;
294 
295     if ( NULL == socketarg || NULL == soip ||
296 		PRLDAP_SOCKETINFO_SIZE != soip->soinfo_size ) {
297 	return( LDAP_PARAM_ERROR );
298     }
299 
300     prsockp = (PRLDAPIOSocketArg *)socketarg;
301     soip->soinfo_prfd = prsockp->prsock_prfd;
302     soip->soinfo_appdata = prsockp->prsock_appdata;
303 
304     return( LDAP_SUCCESS );
305 }
306 
307 /*
308  * Function: prldap_get_default_socket_info().
309  *
310  * Given an LDAP session handle, retrieve socket specific information.
311  * If ld is NULL, LDAP_PARAM_ERROR is returned.
312  *
313  * Returns an LDAP API error code (LDAP_SUCCESS if all goes well, in
314  * which case the fields in the structure that soip points to are filled in).
315  */
316 int LDAP_CALL
317 prldap_get_default_socket_info( LDAP *ld, PRLDAPSocketInfo *soip )
318 {
319     int rc;
320     PRLDAPIOSocketArg *prsockp;
321 
322 
323     if ( NULL == soip || PRLDAP_SOCKETINFO_SIZE != soip->soinfo_size ) {
324         ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL );
325         return( LDAP_PARAM_ERROR );
326     }
327 
328     if ( NULL != ld ) {
329         if ( LDAP_SUCCESS !=
330                 ( rc = prldap_socket_arg_from_ld( ld, &prsockp ))) {
331             return( rc );
332         }
333     } else {
334         ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL );
335         return( LDAP_PARAM_ERROR );
336     }
337 
338     soip->soinfo_prfd = prsockp->prsock_prfd;
339     soip->soinfo_appdata = prsockp->prsock_appdata;
340 
341     return( LDAP_SUCCESS );
342 }
343 
344 
345 /*
346  * Function: prldap_set_default_socket_info().
347  *
348  * Given an LDAP session handle, set socket specific information.
349  * If ld is NULL, LDAP_PARAM_ERROR is returned.
350  *
351  * Returns an LDAP API error code (LDAP_SUCCESS if all goes well, in
352  * which case the fields in the structure that soip points to are filled in).
353  */
354 int LDAP_CALL
355 prldap_set_default_socket_info( LDAP *ld, PRLDAPSocketInfo *soip )
356 {
357     int rc;
358     PRLDAPIOSocketArg *prsockp;
359 
360 
361     if ( NULL == soip || PRLDAP_SOCKETINFO_SIZE != soip->soinfo_size ) {
362         ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL );
363         return( LDAP_PARAM_ERROR );
364     }
365 
366     if ( NULL != ld ) {
367         if ( LDAP_SUCCESS !=
368                 ( rc = prldap_socket_arg_from_ld( ld, &prsockp ))) {
369             return( rc );
370         }
371     } else {
372         ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL );
373         return( LDAP_PARAM_ERROR );
374     }
375 
376     prsockp->prsock_prfd = soip->soinfo_prfd;
377     prsockp->prsock_appdata = soip->soinfo_appdata;
378 
379     return( LDAP_SUCCESS );
380 }
381