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 static const LDAPAPIFeatureInfo features[] = {
20 #ifdef LDAP_API_FEATURE_X_OPENLDAP
21 { /* OpenLDAP Extensions API Feature */
22 LDAP_FEATURE_INFO_VERSION,
24 LDAP_API_FEATURE_X_OPENLDAP
28 #ifdef LDAP_API_FEATURE_THREAD_SAFE
29 { /* Basic Thread Safe */
30 LDAP_FEATURE_INFO_VERSION,
32 LDAP_API_FEATURE_THREAD_SAFE
35 #ifdef LDAP_API_FEATURE_SESSION_THREAD_SAFE
36 { /* Session Thread Safe */
37 LDAP_FEATURE_INFO_VERSION,
38 "SESSION_THREAD_SAFE",
39 LDAP_API_FEATURE_SESSION_THREAD_SAFE
42 #ifdef LDAP_API_FEATURE_OPERATION_THREAD_SAFE
43 { /* Operation Thread Safe */
44 LDAP_FEATURE_INFO_VERSION,
45 "OPERATION_THREAD_SAFE",
46 LDAP_API_FEATURE_OPERATION_THREAD_SAFE
49 #ifdef LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
50 { /* OpenLDAP Reentrant */
51 LDAP_FEATURE_INFO_VERSION,
52 "X_OPENLDAP_REENTRANT",
53 LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
56 #if defined( LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE ) && \
57 defined( LDAP_THREAD_SAFE )
58 { /* OpenLDAP Thread Safe */
59 LDAP_FEATURE_INFO_VERSION,
60 "X_OPENLDAP_THREAD_SAFE",
61 LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE
64 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS
66 LDAP_FEATURE_INFO_VERSION,
68 LDAP_API_FEATURE_X_OPENLDAP_V2_DNS
71 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
73 LDAP_FEATURE_INFO_VERSION,
74 "X_OPENLDAP_V2_REFERRALS",
75 LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
87 const struct ldapoptions *lo;
89 if( ldap_int_global_options.ldo_valid != LDAP_INITIALIZED ) {
90 ldap_int_initialize(NULL);
94 lo = &ldap_int_global_options;
97 assert( LDAP_VALID( ld ) );
99 if( !LDAP_VALID( ld ) ) {
100 return LDAP_OPT_ERROR;
103 lo = &ld->ld_options;
106 if(outvalue == NULL) {
107 /* no place to get to */
108 return LDAP_OPT_ERROR;
112 case LDAP_OPT_API_INFO: {
113 struct ldapapiinfo *info = (struct ldapapiinfo *) outvalue;
116 /* outvalue must point to an apiinfo structure */
117 return LDAP_OPT_ERROR;
120 if(info->ldapai_info_version != LDAP_API_INFO_VERSION) {
121 /* api info version mismatch */
122 info->ldapai_info_version = LDAP_API_INFO_VERSION;
123 return LDAP_OPT_ERROR;
126 info->ldapai_api_version = LDAP_API_VERSION;
127 info->ldapai_api_version = LDAP_API_VERSION;
128 info->ldapai_protocol_version = LDAP_VERSION_MAX;
130 if(features[0].ldapaif_name == NULL) {
131 info->ldapai_extensions = NULL;
134 info->ldapai_extensions = LDAP_MALLOC(sizeof(char *) *
135 sizeof(features)/sizeof(LDAPAPIFeatureInfo));
137 for(i=0; features[i].ldapaif_name != NULL; i++) {
138 info->ldapai_extensions[i] =
139 LDAP_STRDUP(features[i].ldapaif_name);
142 info->ldapai_extensions[i] = NULL;
145 info->ldapai_vendor_name = LDAP_STRDUP(LDAP_VENDOR_NAME);
146 info->ldapai_vendor_version = LDAP_VENDOR_VERSION;
148 return LDAP_OPT_SUCCESS;
157 * (ber_socket_t *) outvalue = ber_pvt_sb_get_desc( &(ld->ld_sb) );
158 return LDAP_OPT_SUCCESS;
160 case LDAP_OPT_TIMEOUT:
161 /* the caller has to free outvalue ! */
162 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_api) != 0 )
164 return LDAP_OPT_ERROR;
166 return LDAP_OPT_SUCCESS;
168 case LDAP_OPT_NETWORK_TIMEOUT:
169 /* the caller has to free outvalue ! */
170 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_net ) != 0 )
172 return LDAP_OPT_ERROR;
174 return LDAP_OPT_SUCCESS;
177 * (int *) outvalue = lo->ldo_deref;
178 return LDAP_OPT_SUCCESS;
180 case LDAP_OPT_SIZELIMIT:
181 * (int *) outvalue = lo->ldo_sizelimit;
182 return LDAP_OPT_SUCCESS;
184 case LDAP_OPT_TIMELIMIT:
185 * (int *) outvalue = lo->ldo_timelimit;
186 return LDAP_OPT_SUCCESS;
188 case LDAP_OPT_REFERRALS:
189 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_REFERRALS);
190 return LDAP_OPT_SUCCESS;
192 case LDAP_OPT_RESTART:
193 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_RESTART);
194 return LDAP_OPT_SUCCESS;
196 case LDAP_OPT_DNS: /* LDAPv2 */
197 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_DNS);
198 return LDAP_OPT_SUCCESS;
200 case LDAP_OPT_PROTOCOL_VERSION:
201 * (int *) outvalue = lo->ldo_version;
202 return LDAP_OPT_SUCCESS;
204 case LDAP_OPT_SERVER_CONTROLS:
205 * (LDAPControl ***) outvalue =
206 ldap_controls_dup( lo->ldo_sctrls );
208 return LDAP_OPT_SUCCESS;
210 case LDAP_OPT_CLIENT_CONTROLS:
211 * (LDAPControl ***) outvalue =
212 ldap_controls_dup( lo->ldo_cctrls );
214 return LDAP_OPT_SUCCESS;
216 case LDAP_OPT_HOST_NAME:
217 * (char **) outvalue = ldap_url_list2hosts(lo->ldo_defludp);
218 return LDAP_OPT_SUCCESS;
221 * (char **) outvalue = ldap_url_list2urls(lo->ldo_defludp);
222 return LDAP_OPT_SUCCESS;
224 case LDAP_OPT_ERROR_NUMBER:
229 * (int *) outvalue = ld->ld_errno;
230 return LDAP_OPT_SUCCESS;
232 case LDAP_OPT_ERROR_STRING:
238 if( ld->ld_error == NULL ) {
239 * (char **) outvalue = NULL;
241 * (char **) outvalue = LDAP_STRDUP(ld->ld_error);
244 return LDAP_OPT_SUCCESS;
246 case LDAP_OPT_MATCHED_DN:
252 if( ld->ld_matched == NULL ) {
253 * (char **) outvalue = NULL;
255 * (char **) outvalue = LDAP_STRDUP(ld->ld_matched);
258 return LDAP_OPT_SUCCESS;
260 case LDAP_OPT_API_FEATURE_INFO: {
261 LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue;
264 if(info == NULL) return LDAP_OPT_ERROR;
266 if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) {
267 /* api info version mismatch */
268 info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
269 return LDAP_OPT_ERROR;
272 if(info->ldapaif_name == NULL) return LDAP_OPT_ERROR;
274 for(i=0; features[i].ldapaif_name != NULL; i++) {
275 if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) {
276 info->ldapaif_version =
277 features[i].ldapaif_version;
278 return LDAP_OPT_SUCCESS;
284 case LDAP_OPT_DEBUG_LEVEL:
285 * (int *) outvalue = lo->ldo_debug;
286 return LDAP_OPT_SUCCESS;
290 if ( ldap_pvt_tls_get_option((struct ldapoptions *)lo, option, outvalue ) == 0 )
291 return LDAP_OPT_SUCCESS;
293 #ifdef HAVE_CYRUS_SASL
294 if ( ldap_pvt_sasl_get_option(ld, option, outvalue ) == 0 )
295 return LDAP_OPT_SUCCESS;
301 return LDAP_OPT_ERROR;
308 LDAP_CONST void *invalue)
310 struct ldapoptions *lo;
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( ldap_int_global_options.ldo_valid != LDAP_INITIALIZED ) {
322 ldap_int_initialize(dbglvl);
326 lo = &ldap_int_global_options;
329 assert( LDAP_VALID( ld ) );
331 if( !LDAP_VALID( ld ) ) {
332 return LDAP_OPT_ERROR;
335 lo = &ld->ld_options;
339 case LDAP_OPT_REFERRALS:
340 if(invalue == LDAP_OPT_OFF) {
341 LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS);
343 LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS);
345 return LDAP_OPT_SUCCESS;
347 case LDAP_OPT_RESTART:
348 if(invalue == LDAP_OPT_OFF) {
349 LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART);
351 LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART);
353 return LDAP_OPT_SUCCESS;
356 /* options which can withstand invalue == NULL */
358 case LDAP_OPT_SERVER_CONTROLS: {
359 LDAPControl *const *controls =
360 (LDAPControl *const *) invalue;
362 ldap_controls_free( lo->ldo_sctrls );
364 if( controls == NULL || *controls == NULL ) {
365 lo->ldo_sctrls = NULL;
366 return LDAP_OPT_SUCCESS;
369 lo->ldo_sctrls = ldap_controls_dup( controls );
371 if(lo->ldo_sctrls == NULL) {
372 /* memory allocation error ? */
375 } return LDAP_OPT_SUCCESS;
377 case LDAP_OPT_CLIENT_CONTROLS: {
378 LDAPControl *const *controls =
379 (LDAPControl *const *) invalue;
381 ldap_controls_free( lo->ldo_cctrls );
383 if( controls == NULL || *controls == NULL ) {
384 lo->ldo_cctrls = NULL;
385 return LDAP_OPT_SUCCESS;
388 lo->ldo_cctrls = ldap_controls_dup( controls );
390 if(lo->ldo_cctrls == NULL) {
391 /* memory allocation error ? */
394 } return LDAP_OPT_SUCCESS;
396 case LDAP_OPT_TIMEOUT: {
397 const struct timeval *tv =
398 (const struct timeval *) invalue;
400 if ( lo->ldo_tm_api != NULL ) {
401 LDAP_FREE( lo->ldo_tm_api );
402 lo->ldo_tm_api = NULL;
405 if ( ldap_int_timeval_dup( &lo->ldo_tm_api, tv ) != 0 ) {
406 return LDAP_OPT_ERROR;
408 } return LDAP_OPT_SUCCESS;
410 case LDAP_OPT_NETWORK_TIMEOUT: {
411 const struct timeval *tv =
412 (const struct timeval *) invalue;
414 if ( lo->ldo_tm_net != NULL ) {
415 LDAP_FREE( lo->ldo_tm_net );
416 lo->ldo_tm_net = NULL;
419 if ( ldap_int_timeval_dup( &lo->ldo_tm_net, tv ) != 0 ) {
420 return LDAP_OPT_ERROR;
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;