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