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 struct ldapoptions *lo;
84 /* Get pointer to global option structure */
85 lo = LDAP_INT_GLOBAL_OPT();
87 return LDAP_NO_MEMORY;
90 if( lo->ldo_valid != LDAP_INITIALIZED ) {
91 ldap_int_initialize(lo, NULL);
95 assert( LDAP_VALID( ld ) );
97 if( !LDAP_VALID( ld ) ) {
98 return LDAP_OPT_ERROR;
101 lo = &ld->ld_options;
104 if(outvalue == NULL) {
105 /* no place to get to */
106 return LDAP_OPT_ERROR;
110 case LDAP_OPT_API_INFO: {
111 struct ldapapiinfo *info = (struct ldapapiinfo *) outvalue;
114 /* outvalue must point to an apiinfo structure */
115 return LDAP_OPT_ERROR;
118 if(info->ldapai_info_version != LDAP_API_INFO_VERSION) {
119 /* api info version mismatch */
120 info->ldapai_info_version = LDAP_API_INFO_VERSION;
121 return LDAP_OPT_ERROR;
124 info->ldapai_api_version = LDAP_API_VERSION;
125 info->ldapai_api_version = LDAP_API_VERSION;
126 info->ldapai_protocol_version = LDAP_VERSION_MAX;
128 if(features[0].ldapaif_name == NULL) {
129 info->ldapai_extensions = NULL;
132 info->ldapai_extensions = LDAP_MALLOC(sizeof(char *) *
133 sizeof(features)/sizeof(LDAPAPIFeatureInfo));
135 for(i=0; features[i].ldapaif_name != NULL; i++) {
136 info->ldapai_extensions[i] =
137 LDAP_STRDUP(features[i].ldapaif_name);
140 info->ldapai_extensions[i] = NULL;
143 info->ldapai_vendor_name = LDAP_STRDUP(LDAP_VENDOR_NAME);
144 info->ldapai_vendor_version = LDAP_VENDOR_VERSION;
146 return LDAP_OPT_SUCCESS;
150 if( ld == NULL || ld->ld_sb == NULL ) {
155 ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, outvalue );
156 return LDAP_OPT_SUCCESS;
158 case LDAP_OPT_TIMEOUT:
159 /* the caller has to free outvalue ! */
160 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_api) != 0 )
162 return LDAP_OPT_ERROR;
164 return LDAP_OPT_SUCCESS;
166 case LDAP_OPT_NETWORK_TIMEOUT:
167 /* the caller has to free outvalue ! */
168 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_net ) != 0 )
170 return LDAP_OPT_ERROR;
172 return LDAP_OPT_SUCCESS;
175 * (int *) outvalue = lo->ldo_deref;
176 return LDAP_OPT_SUCCESS;
178 case LDAP_OPT_SIZELIMIT:
179 * (int *) outvalue = lo->ldo_sizelimit;
180 return LDAP_OPT_SUCCESS;
182 case LDAP_OPT_TIMELIMIT:
183 * (int *) outvalue = lo->ldo_timelimit;
184 return LDAP_OPT_SUCCESS;
186 case LDAP_OPT_REFERRALS:
187 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_REFERRALS);
188 return LDAP_OPT_SUCCESS;
190 case LDAP_OPT_RESTART:
191 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_RESTART);
192 return LDAP_OPT_SUCCESS;
194 case LDAP_OPT_PROTOCOL_VERSION:
195 * (int *) outvalue = lo->ldo_version;
196 return LDAP_OPT_SUCCESS;
198 case LDAP_OPT_SERVER_CONTROLS:
199 * (LDAPControl ***) outvalue =
200 ldap_controls_dup( lo->ldo_sctrls );
202 return LDAP_OPT_SUCCESS;
204 case LDAP_OPT_CLIENT_CONTROLS:
205 * (LDAPControl ***) outvalue =
206 ldap_controls_dup( lo->ldo_cctrls );
208 return LDAP_OPT_SUCCESS;
210 case LDAP_OPT_HOST_NAME:
211 * (char **) outvalue = ldap_url_list2hosts(lo->ldo_defludp);
212 return LDAP_OPT_SUCCESS;
215 * (char **) outvalue = ldap_url_list2urls(lo->ldo_defludp);
216 return LDAP_OPT_SUCCESS;
218 case LDAP_OPT_ERROR_NUMBER:
223 * (int *) outvalue = ld->ld_errno;
224 return LDAP_OPT_SUCCESS;
226 case LDAP_OPT_ERROR_STRING:
232 if( ld->ld_error == NULL ) {
233 * (char **) outvalue = NULL;
235 * (char **) outvalue = LDAP_STRDUP(ld->ld_error);
238 return LDAP_OPT_SUCCESS;
240 case LDAP_OPT_MATCHED_DN:
246 if( ld->ld_matched == NULL ) {
247 * (char **) outvalue = NULL;
249 * (char **) outvalue = LDAP_STRDUP(ld->ld_matched);
252 return LDAP_OPT_SUCCESS;
254 case LDAP_OPT_API_FEATURE_INFO: {
255 LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue;
258 if(info == NULL) return LDAP_OPT_ERROR;
260 if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) {
261 /* api info version mismatch */
262 info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
263 return LDAP_OPT_ERROR;
266 if(info->ldapaif_name == NULL) return LDAP_OPT_ERROR;
268 for(i=0; features[i].ldapaif_name != NULL; i++) {
269 if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) {
270 info->ldapaif_version =
271 features[i].ldapaif_version;
272 return LDAP_OPT_SUCCESS;
278 case LDAP_OPT_DEBUG_LEVEL:
279 * (int *) outvalue = lo->ldo_debug;
280 return LDAP_OPT_SUCCESS;
284 if ( ldap_pvt_tls_get_option((struct ldapoptions *)lo, option, outvalue ) == 0 )
285 return LDAP_OPT_SUCCESS;
287 #ifdef HAVE_CYRUS_SASL
288 if ( ldap_int_sasl_get_option(ld, option, outvalue ) == 0 )
289 return LDAP_OPT_SUCCESS;
295 return LDAP_OPT_ERROR;
302 LDAP_CONST void *invalue)
304 struct ldapoptions *lo;
307 /* Get pointer to global option structure */
308 lo = LDAP_INT_GLOBAL_OPT();
310 return LDAP_NO_MEMORY;
314 * The architecture to turn on debugging has a chicken and egg
315 * problem. Thus, we introduce a fix here.
318 if (option == LDAP_OPT_DEBUG_LEVEL)
319 dbglvl = (int *) invalue;
321 if( lo->ldo_valid != LDAP_INITIALIZED ) {
322 ldap_int_initialize(lo, dbglvl);
326 assert( LDAP_VALID( ld ) );
328 if( !LDAP_VALID( ld ) ) {
329 return LDAP_OPT_ERROR;
332 lo = &ld->ld_options;
336 case LDAP_OPT_REFERRALS:
337 if(invalue == LDAP_OPT_OFF) {
338 LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS);
340 LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS);
342 return LDAP_OPT_SUCCESS;
344 case LDAP_OPT_RESTART:
345 if(invalue == LDAP_OPT_OFF) {
346 LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART);
348 LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART);
350 return LDAP_OPT_SUCCESS;
353 /* options which can withstand invalue == NULL */
355 case LDAP_OPT_SERVER_CONTROLS: {
356 LDAPControl *const *controls =
357 (LDAPControl *const *) invalue;
359 ldap_controls_free( lo->ldo_sctrls );
361 if( controls == NULL || *controls == NULL ) {
362 lo->ldo_sctrls = NULL;
363 return LDAP_OPT_SUCCESS;
366 lo->ldo_sctrls = ldap_controls_dup( controls );
368 if(lo->ldo_sctrls == NULL) {
369 /* memory allocation error ? */
372 } return LDAP_OPT_SUCCESS;
374 case LDAP_OPT_CLIENT_CONTROLS: {
375 LDAPControl *const *controls =
376 (LDAPControl *const *) invalue;
378 ldap_controls_free( lo->ldo_cctrls );
380 if( controls == NULL || *controls == NULL ) {
381 lo->ldo_cctrls = NULL;
382 return LDAP_OPT_SUCCESS;
385 lo->ldo_cctrls = ldap_controls_dup( controls );
387 if(lo->ldo_cctrls == NULL) {
388 /* memory allocation error ? */
391 } return LDAP_OPT_SUCCESS;
393 case LDAP_OPT_TIMEOUT: {
394 const struct timeval *tv =
395 (const struct timeval *) invalue;
397 if ( lo->ldo_tm_api != NULL ) {
398 LDAP_FREE( lo->ldo_tm_api );
399 lo->ldo_tm_api = NULL;
402 if ( ldap_int_timeval_dup( &lo->ldo_tm_api, tv ) != 0 ) {
403 return LDAP_OPT_ERROR;
405 } return LDAP_OPT_SUCCESS;
407 case LDAP_OPT_NETWORK_TIMEOUT: {
408 const struct timeval *tv =
409 (const struct timeval *) invalue;
411 if ( lo->ldo_tm_net != NULL ) {
412 LDAP_FREE( lo->ldo_tm_net );
413 lo->ldo_tm_net = NULL;
416 if ( ldap_int_timeval_dup( &lo->ldo_tm_net, tv ) != 0 ) {
417 return LDAP_OPT_ERROR;
419 } return LDAP_OPT_SUCCESS;
421 /* Only accessed from inside this function by ldap_set_rebind_proc() */
422 case LDAP_OPT_REBIND_PROC: {
423 lo->ldo_rebindproc = (LDAP_REBIND_PROC *)invalue;
424 } return LDAP_OPT_SUCCESS;
427 if(invalue == NULL) {
428 /* no place to set from */
429 return LDAP_OPT_ERROR;
432 /* options which cannot withstand invalue == NULL */
435 case LDAP_OPT_API_INFO:
441 lo->ldo_deref = * (const int *) invalue;
442 return LDAP_OPT_SUCCESS;
444 case LDAP_OPT_SIZELIMIT:
445 lo->ldo_sizelimit = * (const int *) invalue;
446 return LDAP_OPT_SUCCESS;
448 case LDAP_OPT_TIMELIMIT:
449 lo->ldo_timelimit = * (const int *) invalue;
450 return LDAP_OPT_SUCCESS;
452 case LDAP_OPT_PROTOCOL_VERSION: {
453 int vers = * (const int *) invalue;
454 if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) {
458 lo->ldo_version = vers;
459 } return LDAP_OPT_SUCCESS;
462 case LDAP_OPT_HOST_NAME: {
463 const char *host = (const char *) invalue;
464 LDAPURLDesc *ludlist = NULL;
465 int rc = LDAP_OPT_SUCCESS;
468 rc = ldap_url_parsehosts(&ludlist, host);
470 } else if(ld == NULL) {
472 * must want global default returned
473 * to initial condition.
475 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
479 * must want the session default
480 * updated to the current global default
482 ludlist = ldap_url_duplist(
483 ldap_int_global_options.ldo_defludp);
488 if (rc == LDAP_OPT_SUCCESS) {
489 if (lo->ldo_defludp != NULL)
490 ldap_free_urllist(lo->ldo_defludp);
491 lo->ldo_defludp = ludlist;
497 const char *urls = (const char *) invalue;
498 LDAPURLDesc *ludlist = NULL;
499 int rc = LDAP_OPT_SUCCESS;
502 rc = ldap_url_parselist(&ludlist, urls);
504 } else if(ld == NULL) {
506 * must want global default returned
507 * to initial condition.
509 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
513 * must want the session default
514 * updated to the current global default
516 ludlist = ldap_url_duplist(
517 ldap_int_global_options.ldo_defludp);
522 if (rc == LDAP_OPT_SUCCESS) {
523 if (lo->ldo_defludp != NULL)
524 ldap_free_urllist(lo->ldo_defludp);
525 lo->ldo_defludp = ludlist;
530 case LDAP_OPT_ERROR_NUMBER: {
531 int err = * (const int *) invalue;
534 /* need a struct ldap */
539 } return LDAP_OPT_SUCCESS;
541 case LDAP_OPT_ERROR_STRING: {
542 const char *err = (const char *) invalue;
545 /* need a struct ldap */
550 LDAP_FREE(ld->ld_error);
553 ld->ld_error = LDAP_STRDUP(err);
554 } return LDAP_OPT_SUCCESS;
556 case LDAP_OPT_MATCHED_DN: {
557 const char *err = (const char *) invalue;
560 /* need a struct ldap */
564 if( ld->ld_matched ) {
565 LDAP_FREE(ld->ld_matched);
568 ld->ld_matched = LDAP_STRDUP(err);
569 } return LDAP_OPT_SUCCESS;
571 case LDAP_OPT_API_FEATURE_INFO:
575 case LDAP_OPT_DEBUG_LEVEL:
576 lo->ldo_debug = * (const int *) invalue;
577 return LDAP_OPT_SUCCESS;
581 if ( ldap_pvt_tls_set_option( lo, option, (void *)invalue ) == 0 )
582 return LDAP_OPT_SUCCESS;
584 #ifdef HAVE_CYRUS_SASL
585 if ( ldap_int_sasl_set_option( ld, option, (void *)invalue ) == 0 )
586 return LDAP_OPT_SUCCESS;
591 return LDAP_OPT_ERROR;
595 ldap_set_rebind_proc( LDAP *ld, LDAP_REBIND_PROC *rebind_proc)
597 return( ldap_set_option( ld, LDAP_OPT_REBIND_PROC, (void *)rebind_proc));