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_PROTOCOL_VERSION:
192 * (int *) outvalue = lo->ldo_version;
193 return LDAP_OPT_SUCCESS;
195 case LDAP_OPT_SERVER_CONTROLS:
196 * (LDAPControl ***) outvalue =
197 ldap_controls_dup( lo->ldo_sctrls );
199 return LDAP_OPT_SUCCESS;
201 case LDAP_OPT_CLIENT_CONTROLS:
202 * (LDAPControl ***) outvalue =
203 ldap_controls_dup( lo->ldo_cctrls );
205 return LDAP_OPT_SUCCESS;
207 case LDAP_OPT_HOST_NAME:
208 * (char **) outvalue = ldap_url_list2hosts(lo->ldo_defludp);
209 return LDAP_OPT_SUCCESS;
212 * (char **) outvalue = ldap_url_list2urls(lo->ldo_defludp);
213 return LDAP_OPT_SUCCESS;
215 case LDAP_OPT_ERROR_NUMBER:
220 * (int *) outvalue = ld->ld_errno;
221 return LDAP_OPT_SUCCESS;
223 case LDAP_OPT_ERROR_STRING:
229 if( ld->ld_error == NULL ) {
230 * (char **) outvalue = NULL;
232 * (char **) outvalue = LDAP_STRDUP(ld->ld_error);
235 return LDAP_OPT_SUCCESS;
237 case LDAP_OPT_MATCHED_DN:
243 if( ld->ld_matched == NULL ) {
244 * (char **) outvalue = NULL;
246 * (char **) outvalue = LDAP_STRDUP(ld->ld_matched);
249 return LDAP_OPT_SUCCESS;
251 case LDAP_OPT_API_FEATURE_INFO: {
252 LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue;
255 if(info == NULL) return LDAP_OPT_ERROR;
257 if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) {
258 /* api info version mismatch */
259 info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
260 return LDAP_OPT_ERROR;
263 if(info->ldapaif_name == NULL) return LDAP_OPT_ERROR;
265 for(i=0; features[i].ldapaif_name != NULL; i++) {
266 if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) {
267 info->ldapaif_version =
268 features[i].ldapaif_version;
269 return LDAP_OPT_SUCCESS;
275 case LDAP_OPT_DEBUG_LEVEL:
276 * (int *) outvalue = lo->ldo_debug;
277 return LDAP_OPT_SUCCESS;
281 if ( ldap_pvt_tls_get_option((struct ldapoptions *)lo, option, outvalue ) == 0 )
282 return LDAP_OPT_SUCCESS;
284 #ifdef HAVE_CYRUS_SASL
285 if ( ldap_pvt_sasl_get_option(ld, option, outvalue ) == 0 )
286 return LDAP_OPT_SUCCESS;
292 return LDAP_OPT_ERROR;
299 LDAP_CONST void *invalue)
301 struct ldapoptions *lo;
305 * The architecture to turn on debugging has a chicken and egg
306 * problem. Thus, we introduce a fix here.
309 if (option == LDAP_OPT_DEBUG_LEVEL)
310 dbglvl = (int *) invalue;
312 if( ldap_int_global_options.ldo_valid != LDAP_INITIALIZED ) {
313 ldap_int_initialize(dbglvl);
317 lo = &ldap_int_global_options;
320 assert( LDAP_VALID( ld ) );
322 if( !LDAP_VALID( ld ) ) {
323 return LDAP_OPT_ERROR;
326 lo = &ld->ld_options;
330 case LDAP_OPT_REFERRALS:
331 if(invalue == LDAP_OPT_OFF) {
332 LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS);
334 LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS);
336 return LDAP_OPT_SUCCESS;
338 case LDAP_OPT_RESTART:
339 if(invalue == LDAP_OPT_OFF) {
340 LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART);
342 LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART);
344 return LDAP_OPT_SUCCESS;
347 /* options which can withstand invalue == NULL */
349 case LDAP_OPT_SERVER_CONTROLS: {
350 LDAPControl *const *controls =
351 (LDAPControl *const *) invalue;
353 ldap_controls_free( lo->ldo_sctrls );
355 if( controls == NULL || *controls == NULL ) {
356 lo->ldo_sctrls = NULL;
357 return LDAP_OPT_SUCCESS;
360 lo->ldo_sctrls = ldap_controls_dup( controls );
362 if(lo->ldo_sctrls == NULL) {
363 /* memory allocation error ? */
366 } return LDAP_OPT_SUCCESS;
368 case LDAP_OPT_CLIENT_CONTROLS: {
369 LDAPControl *const *controls =
370 (LDAPControl *const *) invalue;
372 ldap_controls_free( lo->ldo_cctrls );
374 if( controls == NULL || *controls == NULL ) {
375 lo->ldo_cctrls = NULL;
376 return LDAP_OPT_SUCCESS;
379 lo->ldo_cctrls = ldap_controls_dup( controls );
381 if(lo->ldo_cctrls == NULL) {
382 /* memory allocation error ? */
385 } return LDAP_OPT_SUCCESS;
387 case LDAP_OPT_TIMEOUT: {
388 const struct timeval *tv =
389 (const struct timeval *) invalue;
391 if ( lo->ldo_tm_api != NULL ) {
392 LDAP_FREE( lo->ldo_tm_api );
393 lo->ldo_tm_api = NULL;
396 if ( ldap_int_timeval_dup( &lo->ldo_tm_api, tv ) != 0 ) {
397 return LDAP_OPT_ERROR;
399 } return LDAP_OPT_SUCCESS;
401 case LDAP_OPT_NETWORK_TIMEOUT: {
402 const struct timeval *tv =
403 (const struct timeval *) invalue;
405 if ( lo->ldo_tm_net != NULL ) {
406 LDAP_FREE( lo->ldo_tm_net );
407 lo->ldo_tm_net = NULL;
410 if ( ldap_int_timeval_dup( &lo->ldo_tm_net, tv ) != 0 ) {
411 return LDAP_OPT_ERROR;
413 } return LDAP_OPT_SUCCESS;
415 /* Only accessed from inside this function by ldap_set_rebind_proc() */
416 case LDAP_OPT_REBIND_PROC: {
417 lo->ldo_rebindproc = (LDAP_REBIND_PROC *)invalue;
418 } return LDAP_OPT_SUCCESS;
421 if(invalue == NULL) {
422 /* no place to set from */
423 return LDAP_OPT_ERROR;
426 /* options which cannot withstand invalue == NULL */
429 case LDAP_OPT_API_INFO:
435 lo->ldo_deref = * (const int *) invalue;
436 return LDAP_OPT_SUCCESS;
438 case LDAP_OPT_SIZELIMIT:
439 lo->ldo_sizelimit = * (const int *) invalue;
440 return LDAP_OPT_SUCCESS;
442 case LDAP_OPT_TIMELIMIT:
443 lo->ldo_timelimit = * (const int *) invalue;
444 return LDAP_OPT_SUCCESS;
446 case LDAP_OPT_PROTOCOL_VERSION: {
447 int vers = * (const int *) invalue;
448 if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) {
452 lo->ldo_version = vers;
453 } return LDAP_OPT_SUCCESS;
456 case LDAP_OPT_HOST_NAME: {
457 const char *host = (const char *) invalue;
458 LDAPURLDesc *ludlist = NULL;
459 int rc = LDAP_OPT_SUCCESS;
462 rc = ldap_url_parsehosts(&ludlist, host);
464 } else if(ld == NULL) {
466 * must want global default returned
467 * to initial condition.
469 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
473 * must want the session default
474 * updated to the current global default
476 ludlist = ldap_url_duplist(
477 ldap_int_global_options.ldo_defludp);
482 if (rc == LDAP_OPT_SUCCESS) {
483 if (lo->ldo_defludp != NULL)
484 ldap_free_urllist(lo->ldo_defludp);
485 lo->ldo_defludp = ludlist;
491 const char *urls = (const char *) invalue;
492 LDAPURLDesc *ludlist = NULL;
493 int rc = LDAP_OPT_SUCCESS;
496 rc = ldap_url_parselist(&ludlist, urls);
498 } else if(ld == NULL) {
500 * must want global default returned
501 * to initial condition.
503 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
507 * must want the session default
508 * updated to the current global default
510 ludlist = ldap_url_duplist(
511 ldap_int_global_options.ldo_defludp);
516 if (rc == LDAP_OPT_SUCCESS) {
517 if (lo->ldo_defludp != NULL)
518 ldap_free_urllist(lo->ldo_defludp);
519 lo->ldo_defludp = ludlist;
524 case LDAP_OPT_ERROR_NUMBER: {
525 int err = * (const int *) invalue;
528 /* need a struct ldap */
533 } return LDAP_OPT_SUCCESS;
535 case LDAP_OPT_ERROR_STRING: {
536 const char *err = (const char *) invalue;
539 /* need a struct ldap */
544 LDAP_FREE(ld->ld_error);
547 ld->ld_error = LDAP_STRDUP(err);
548 } return LDAP_OPT_SUCCESS;
550 case LDAP_OPT_MATCHED_DN: {
551 const char *err = (const char *) invalue;
554 /* need a struct ldap */
558 if( ld->ld_matched ) {
559 LDAP_FREE(ld->ld_matched);
562 ld->ld_matched = LDAP_STRDUP(err);
563 } return LDAP_OPT_SUCCESS;
565 case LDAP_OPT_API_FEATURE_INFO:
569 case LDAP_OPT_DEBUG_LEVEL:
570 lo->ldo_debug = * (const int *) invalue;
571 return LDAP_OPT_SUCCESS;
575 if ( ldap_pvt_tls_set_option( lo, option, (void *)invalue ) == 0 )
576 return LDAP_OPT_SUCCESS;
578 #ifdef HAVE_CYRUS_SASL
579 if ( ldap_pvt_sasl_set_option( ld, option, (void *)invalue ) == 0 )
580 return LDAP_OPT_SUCCESS;
585 return LDAP_OPT_ERROR;
589 ldap_set_rebind_proc( LDAP *ld, LDAP_REBIND_PROC *rebind_proc)
591 return( ldap_set_option( ld, LDAP_OPT_REBIND_PROC, (void *)rebind_proc));