3 * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
11 #include <ac/stdlib.h>
13 #include <ac/socket.h>
14 #include <ac/string.h>
19 #define LDAP_OPT_REBIND_PROC 0x4e814d
21 static const LDAPAPIFeatureInfo features[] = {
22 #ifdef LDAP_API_FEATURE_X_OPENLDAP
23 { /* OpenLDAP Extensions API Feature */
24 LDAP_FEATURE_INFO_VERSION,
26 LDAP_API_FEATURE_X_OPENLDAP
30 #ifdef LDAP_API_FEATURE_THREAD_SAFE
31 { /* Basic Thread Safe */
32 LDAP_FEATURE_INFO_VERSION,
34 LDAP_API_FEATURE_THREAD_SAFE
37 #ifdef LDAP_API_FEATURE_SESSION_THREAD_SAFE
38 { /* Session Thread Safe */
39 LDAP_FEATURE_INFO_VERSION,
40 "SESSION_THREAD_SAFE",
41 LDAP_API_FEATURE_SESSION_THREAD_SAFE
44 #ifdef LDAP_API_FEATURE_OPERATION_THREAD_SAFE
45 { /* Operation Thread Safe */
46 LDAP_FEATURE_INFO_VERSION,
47 "OPERATION_THREAD_SAFE",
48 LDAP_API_FEATURE_OPERATION_THREAD_SAFE
51 #ifdef LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
52 { /* OpenLDAP Reentrant */
53 LDAP_FEATURE_INFO_VERSION,
54 "X_OPENLDAP_REENTRANT",
55 LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
58 #if defined( LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE ) && \
59 defined( LDAP_THREAD_SAFE )
60 { /* OpenLDAP Thread Safe */
61 LDAP_FEATURE_INFO_VERSION,
62 "X_OPENLDAP_THREAD_SAFE",
63 LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE
66 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
68 LDAP_FEATURE_INFO_VERSION,
69 "X_OPENLDAP_V2_REFERRALS",
70 LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
82 const struct ldapoptions *lo;
84 if( ldap_int_global_options.ldo_valid != LDAP_INITIALIZED ) {
85 ldap_int_initialize(NULL);
89 lo = &ldap_int_global_options;
92 assert( LDAP_VALID( ld ) );
94 if( !LDAP_VALID( ld ) ) {
95 return LDAP_OPT_ERROR;
101 if(outvalue == NULL) {
102 /* no place to get to */
103 return LDAP_OPT_ERROR;
107 case LDAP_OPT_API_INFO: {
108 struct ldapapiinfo *info = (struct ldapapiinfo *) outvalue;
111 /* outvalue must point to an apiinfo structure */
112 return LDAP_OPT_ERROR;
115 if(info->ldapai_info_version != LDAP_API_INFO_VERSION) {
116 /* api info version mismatch */
117 info->ldapai_info_version = LDAP_API_INFO_VERSION;
118 return LDAP_OPT_ERROR;
121 info->ldapai_api_version = LDAP_API_VERSION;
122 info->ldapai_api_version = LDAP_API_VERSION;
123 info->ldapai_protocol_version = LDAP_VERSION_MAX;
125 if(features[0].ldapaif_name == NULL) {
126 info->ldapai_extensions = NULL;
129 info->ldapai_extensions = LDAP_MALLOC(sizeof(char *) *
130 sizeof(features)/sizeof(LDAPAPIFeatureInfo));
132 for(i=0; features[i].ldapaif_name != NULL; i++) {
133 info->ldapai_extensions[i] =
134 LDAP_STRDUP(features[i].ldapaif_name);
137 info->ldapai_extensions[i] = NULL;
140 info->ldapai_vendor_name = LDAP_STRDUP(LDAP_VENDOR_NAME);
141 info->ldapai_vendor_version = LDAP_VENDOR_VERSION;
143 return LDAP_OPT_SUCCESS;
147 if( ld == NULL || ld->ld_sb == NULL ) {
152 ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, outvalue );
153 return LDAP_OPT_SUCCESS;
155 case LDAP_OPT_TIMEOUT:
156 /* the caller has to free outvalue ! */
157 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_api) != 0 )
159 return LDAP_OPT_ERROR;
161 return LDAP_OPT_SUCCESS;
163 case LDAP_OPT_NETWORK_TIMEOUT:
164 /* the caller has to free outvalue ! */
165 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_net ) != 0 )
167 return LDAP_OPT_ERROR;
169 return LDAP_OPT_SUCCESS;
172 * (int *) outvalue = lo->ldo_deref;
173 return LDAP_OPT_SUCCESS;
175 case LDAP_OPT_SIZELIMIT:
176 * (int *) outvalue = lo->ldo_sizelimit;
177 return LDAP_OPT_SUCCESS;
179 case LDAP_OPT_TIMELIMIT:
180 * (int *) outvalue = lo->ldo_timelimit;
181 return LDAP_OPT_SUCCESS;
183 case LDAP_OPT_REFERRALS:
184 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_REFERRALS);
185 return LDAP_OPT_SUCCESS;
187 case LDAP_OPT_RESTART:
188 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_RESTART);
189 return LDAP_OPT_SUCCESS;
191 case LDAP_OPT_DNS: /* LDAPv2 */
192 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_DNS);
193 return LDAP_OPT_SUCCESS;
195 case LDAP_OPT_PROTOCOL_VERSION:
196 * (int *) outvalue = lo->ldo_version;
197 return LDAP_OPT_SUCCESS;
199 case LDAP_OPT_SERVER_CONTROLS:
200 * (LDAPControl ***) outvalue =
201 ldap_controls_dup( lo->ldo_sctrls );
203 return LDAP_OPT_SUCCESS;
205 case LDAP_OPT_CLIENT_CONTROLS:
206 * (LDAPControl ***) outvalue =
207 ldap_controls_dup( lo->ldo_cctrls );
209 return LDAP_OPT_SUCCESS;
211 case LDAP_OPT_HOST_NAME:
212 * (char **) outvalue = ldap_url_list2hosts(lo->ldo_defludp);
213 return LDAP_OPT_SUCCESS;
216 * (char **) outvalue = ldap_url_list2urls(lo->ldo_defludp);
217 return LDAP_OPT_SUCCESS;
219 case LDAP_OPT_ERROR_NUMBER:
224 * (int *) outvalue = ld->ld_errno;
225 return LDAP_OPT_SUCCESS;
227 case LDAP_OPT_ERROR_STRING:
233 if( ld->ld_error == NULL ) {
234 * (char **) outvalue = NULL;
236 * (char **) outvalue = LDAP_STRDUP(ld->ld_error);
239 return LDAP_OPT_SUCCESS;
241 case LDAP_OPT_MATCHED_DN:
247 if( ld->ld_matched == NULL ) {
248 * (char **) outvalue = NULL;
250 * (char **) outvalue = LDAP_STRDUP(ld->ld_matched);
253 return LDAP_OPT_SUCCESS;
255 case LDAP_OPT_API_FEATURE_INFO: {
256 LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue;
259 if(info == NULL) return LDAP_OPT_ERROR;
261 if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) {
262 /* api info version mismatch */
263 info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
264 return LDAP_OPT_ERROR;
267 if(info->ldapaif_name == NULL) return LDAP_OPT_ERROR;
269 for(i=0; features[i].ldapaif_name != NULL; i++) {
270 if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) {
271 info->ldapaif_version =
272 features[i].ldapaif_version;
273 return LDAP_OPT_SUCCESS;
279 case LDAP_OPT_DEBUG_LEVEL:
280 * (int *) outvalue = lo->ldo_debug;
281 return LDAP_OPT_SUCCESS;
285 if ( ldap_pvt_tls_get_option((struct ldapoptions *)lo, option, outvalue ) == 0 )
286 return LDAP_OPT_SUCCESS;
288 #ifdef HAVE_CYRUS_SASL
289 if ( ldap_pvt_sasl_get_option(ld, option, outvalue ) == 0 )
290 return LDAP_OPT_SUCCESS;
296 return LDAP_OPT_ERROR;
303 LDAP_CONST void *invalue)
305 struct ldapoptions *lo;
309 * The architecture to turn on debugging has a chicken and egg
310 * problem. Thus, we introduce a fix here.
313 if (option == LDAP_OPT_DEBUG_LEVEL)
314 dbglvl = (int *) invalue;
316 if( ldap_int_global_options.ldo_valid != LDAP_INITIALIZED ) {
317 ldap_int_initialize(dbglvl);
321 lo = &ldap_int_global_options;
324 assert( LDAP_VALID( ld ) );
326 if( !LDAP_VALID( ld ) ) {
327 return LDAP_OPT_ERROR;
330 lo = &ld->ld_options;
334 case LDAP_OPT_REFERRALS:
335 if(invalue == LDAP_OPT_OFF) {
336 LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS);
338 LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS);
340 return LDAP_OPT_SUCCESS;
342 case LDAP_OPT_RESTART:
343 if(invalue == LDAP_OPT_OFF) {
344 LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART);
346 LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART);
348 return LDAP_OPT_SUCCESS;
351 /* options which can withstand invalue == NULL */
353 case LDAP_OPT_SERVER_CONTROLS: {
354 LDAPControl *const *controls =
355 (LDAPControl *const *) invalue;
357 ldap_controls_free( lo->ldo_sctrls );
359 if( controls == NULL || *controls == NULL ) {
360 lo->ldo_sctrls = NULL;
361 return LDAP_OPT_SUCCESS;
364 lo->ldo_sctrls = ldap_controls_dup( controls );
366 if(lo->ldo_sctrls == NULL) {
367 /* memory allocation error ? */
370 } return LDAP_OPT_SUCCESS;
372 case LDAP_OPT_CLIENT_CONTROLS: {
373 LDAPControl *const *controls =
374 (LDAPControl *const *) invalue;
376 ldap_controls_free( lo->ldo_cctrls );
378 if( controls == NULL || *controls == NULL ) {
379 lo->ldo_cctrls = NULL;
380 return LDAP_OPT_SUCCESS;
383 lo->ldo_cctrls = ldap_controls_dup( controls );
385 if(lo->ldo_cctrls == NULL) {
386 /* memory allocation error ? */
389 } return LDAP_OPT_SUCCESS;
391 case LDAP_OPT_TIMEOUT: {
392 const struct timeval *tv =
393 (const struct timeval *) invalue;
395 if ( lo->ldo_tm_api != NULL ) {
396 LDAP_FREE( lo->ldo_tm_api );
397 lo->ldo_tm_api = NULL;
400 if ( ldap_int_timeval_dup( &lo->ldo_tm_api, tv ) != 0 ) {
401 return LDAP_OPT_ERROR;
403 } return LDAP_OPT_SUCCESS;
405 case LDAP_OPT_NETWORK_TIMEOUT: {
406 const struct timeval *tv =
407 (const struct timeval *) invalue;
409 if ( lo->ldo_tm_net != NULL ) {
410 LDAP_FREE( lo->ldo_tm_net );
411 lo->ldo_tm_net = NULL;
414 if ( ldap_int_timeval_dup( &lo->ldo_tm_net, tv ) != 0 ) {
415 return LDAP_OPT_ERROR;
417 } return LDAP_OPT_SUCCESS;
419 /* Only accessed from inside this function by ldap_set_rebind_proc() */
420 case LDAP_OPT_REBIND_PROC: {
421 lo->ldo_rebindproc = (LDAP_REBIND_PROC *)invalue;
422 } return LDAP_OPT_SUCCESS;
425 if(invalue == NULL) {
426 /* no place to set from */
427 return LDAP_OPT_ERROR;
430 /* options which cannot withstand invalue == NULL */
433 case LDAP_OPT_API_INFO:
439 lo->ldo_deref = * (const int *) invalue;
440 return LDAP_OPT_SUCCESS;
442 case LDAP_OPT_SIZELIMIT:
443 lo->ldo_sizelimit = * (const int *) invalue;
444 return LDAP_OPT_SUCCESS;
446 case LDAP_OPT_TIMELIMIT:
447 lo->ldo_timelimit = * (const int *) invalue;
448 return LDAP_OPT_SUCCESS;
450 case LDAP_OPT_PROTOCOL_VERSION: {
451 int vers = * (const int *) invalue;
452 if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) {
456 lo->ldo_version = vers;
457 } return LDAP_OPT_SUCCESS;
460 case LDAP_OPT_HOST_NAME: {
461 const char *host = (const char *) invalue;
462 LDAPURLDesc *ludlist = NULL;
463 int rc = LDAP_OPT_SUCCESS;
466 rc = ldap_url_parsehosts(&ludlist, host);
468 } else if(ld == NULL) {
470 * must want global default returned
471 * to initial condition.
473 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
477 * must want the session default
478 * updated to the current global default
480 ludlist = ldap_url_duplist(
481 ldap_int_global_options.ldo_defludp);
486 if (rc == LDAP_OPT_SUCCESS) {
487 if (lo->ldo_defludp != NULL)
488 ldap_free_urllist(lo->ldo_defludp);
489 lo->ldo_defludp = ludlist;
495 const char *urls = (const char *) invalue;
496 LDAPURLDesc *ludlist = NULL;
497 int rc = LDAP_OPT_SUCCESS;
500 rc = ldap_url_parselist(&ludlist, urls);
502 } else if(ld == NULL) {
504 * must want global default returned
505 * to initial condition.
507 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
511 * must want the session default
512 * updated to the current global default
514 ludlist = ldap_url_duplist(
515 ldap_int_global_options.ldo_defludp);
520 if (rc == LDAP_OPT_SUCCESS) {
521 if (lo->ldo_defludp != NULL)
522 ldap_free_urllist(lo->ldo_defludp);
523 lo->ldo_defludp = ludlist;
528 case LDAP_OPT_ERROR_NUMBER: {
529 int err = * (const int *) invalue;
532 /* need a struct ldap */
537 } return LDAP_OPT_SUCCESS;
539 case LDAP_OPT_ERROR_STRING: {
540 const char *err = (const char *) invalue;
543 /* need a struct ldap */
548 LDAP_FREE(ld->ld_error);
551 ld->ld_error = LDAP_STRDUP(err);
552 } return LDAP_OPT_SUCCESS;
554 case LDAP_OPT_MATCHED_DN: {
555 const char *err = (const char *) invalue;
558 /* need a struct ldap */
562 if( ld->ld_matched ) {
563 LDAP_FREE(ld->ld_matched);
566 ld->ld_matched = LDAP_STRDUP(err);
567 } return LDAP_OPT_SUCCESS;
569 case LDAP_OPT_API_FEATURE_INFO:
573 case LDAP_OPT_DEBUG_LEVEL:
574 lo->ldo_debug = * (const int *) invalue;
575 return LDAP_OPT_SUCCESS;
579 if ( ldap_pvt_tls_set_option( lo, option, (void *)invalue ) == 0 )
580 return LDAP_OPT_SUCCESS;
582 #ifdef HAVE_CYRUS_SASL
583 if ( ldap_pvt_sasl_set_option( ld, option, (void *)invalue ) == 0 )
584 return LDAP_OPT_SUCCESS;
589 return LDAP_OPT_ERROR;
593 ldap_set_rebind_proc( LDAP *ld, LDAP_REBIND_PROC *rebind_proc)
595 return( ldap_set_option( ld, LDAP_OPT_REBIND_PROC, (void *)rebind_proc));