Back to index

openldap  2.4.31
options.c
Go to the documentation of this file.
00001 /* $OpenLDAP$ */
00002 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00003  *
00004  * Copyright 1998-2012 The OpenLDAP Foundation.
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted only as authorized by the OpenLDAP
00009  * Public License.
00010  *
00011  * A copy of this license is available in the file LICENSE in the
00012  * top-level directory of the distribution or, alternatively, at
00013  * <http://www.OpenLDAP.org/license.html>.
00014  */
00015 
00016 #include "portable.h"
00017 
00018 #include <stdio.h>
00019 
00020 #include <ac/stdlib.h>
00021 
00022 #include <ac/socket.h>
00023 #include <ac/string.h>
00024 #include <ac/time.h>
00025 
00026 #include "ldap-int.h"
00027 
00028 #define LDAP_OPT_REBIND_PROC 0x4e814d
00029 #define LDAP_OPT_REBIND_PARAMS 0x4e814e
00030 
00031 #define LDAP_OPT_NEXTREF_PROC 0x4e815d
00032 #define LDAP_OPT_NEXTREF_PARAMS 0x4e815e
00033 
00034 #define LDAP_OPT_URLLIST_PROC 0x4e816d
00035 #define LDAP_OPT_URLLIST_PARAMS 0x4e816e
00036 
00037 static const LDAPAPIFeatureInfo features[] = {
00038 #ifdef LDAP_API_FEATURE_X_OPENLDAP
00039        {      /* OpenLDAP Extensions API Feature */
00040               LDAP_FEATURE_INFO_VERSION,
00041               "X_OPENLDAP",
00042               LDAP_API_FEATURE_X_OPENLDAP
00043        },
00044 #endif
00045 
00046 #ifdef LDAP_API_FEATURE_THREAD_SAFE
00047        {      /* Basic Thread Safe */
00048               LDAP_FEATURE_INFO_VERSION,
00049               "THREAD_SAFE",
00050               LDAP_API_FEATURE_THREAD_SAFE
00051        },
00052 #endif
00053 #ifdef LDAP_API_FEATURE_SESSION_THREAD_SAFE
00054        {      /* Session Thread Safe */
00055               LDAP_FEATURE_INFO_VERSION,
00056               "SESSION_THREAD_SAFE",
00057               LDAP_API_FEATURE_SESSION_THREAD_SAFE
00058        },
00059 #endif
00060 #ifdef LDAP_API_FEATURE_OPERATION_THREAD_SAFE
00061        {      /* Operation Thread Safe */
00062               LDAP_FEATURE_INFO_VERSION,
00063               "OPERATION_THREAD_SAFE",
00064               LDAP_API_FEATURE_OPERATION_THREAD_SAFE
00065        },
00066 #endif
00067 #ifdef LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
00068        {      /* OpenLDAP Reentrant */
00069               LDAP_FEATURE_INFO_VERSION,
00070               "X_OPENLDAP_REENTRANT",
00071               LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
00072        },
00073 #endif
00074 #if defined( LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE ) && \
00075        defined( LDAP_THREAD_SAFE )
00076        {      /* OpenLDAP Thread Safe */
00077               LDAP_FEATURE_INFO_VERSION,
00078               "X_OPENLDAP_THREAD_SAFE",
00079               LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE
00080        },
00081 #endif
00082 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
00083        {      /* V2 Referrals */
00084               LDAP_FEATURE_INFO_VERSION,
00085               "X_OPENLDAP_V2_REFERRALS",
00086               LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
00087        },
00088 #endif
00089        {0, NULL, 0}
00090 };
00091 
00092 int
00093 ldap_get_option(
00094        LDAP   *ld,
00095        int           option,
00096        void   *outvalue)
00097 {
00098        struct ldapoptions *lo;
00099        int rc = LDAP_OPT_ERROR;
00100 
00101        /* Get pointer to global option structure */
00102        lo = LDAP_INT_GLOBAL_OPT();   
00103        if (NULL == lo)      {
00104               return LDAP_NO_MEMORY;
00105        }
00106 
00107        if( lo->ldo_valid != LDAP_INITIALIZED ) {
00108               ldap_int_initialize(lo, NULL);
00109        }
00110 
00111        if(ld != NULL) {
00112               assert( LDAP_VALID( ld ) );
00113 
00114               if( !LDAP_VALID( ld ) ) {
00115                      return LDAP_OPT_ERROR;
00116               }
00117 
00118               lo = &ld->ld_options;
00119        }
00120 
00121        if(outvalue == NULL) {
00122               /* no place to get to */
00123               return LDAP_OPT_ERROR;
00124        }
00125 
00126        LDAP_MUTEX_LOCK( &lo->ldo_mutex );
00127 
00128        switch(option) {
00129        case LDAP_OPT_API_INFO: {
00130                      struct ldapapiinfo *info = (struct ldapapiinfo *) outvalue;
00131 
00132                      if(info == NULL) {
00133                             /* outvalue must point to an apiinfo structure */
00134                             break; /* LDAP_OPT_ERROR */
00135                      }
00136 
00137                      if(info->ldapai_info_version != LDAP_API_INFO_VERSION) {
00138                             /* api info version mismatch */
00139                             info->ldapai_info_version = LDAP_API_INFO_VERSION;
00140                             break; /* LDAP_OPT_ERROR */
00141                      }
00142 
00143                      info->ldapai_api_version = LDAP_API_VERSION;
00144                      info->ldapai_protocol_version = LDAP_VERSION_MAX;
00145 
00146                      if(features[0].ldapaif_name == NULL) {
00147                             info->ldapai_extensions = NULL;
00148                      } else {
00149                             int i;
00150                             info->ldapai_extensions = LDAP_MALLOC(sizeof(char *) *
00151                                    sizeof(features)/sizeof(LDAPAPIFeatureInfo));
00152 
00153                             for(i=0; features[i].ldapaif_name != NULL; i++) {
00154                                    info->ldapai_extensions[i] =
00155                                           LDAP_STRDUP(features[i].ldapaif_name);
00156                             }
00157 
00158                             info->ldapai_extensions[i] = NULL;
00159                      }
00160 
00161                      info->ldapai_vendor_name = LDAP_STRDUP(LDAP_VENDOR_NAME);
00162                      info->ldapai_vendor_version = LDAP_VENDOR_VERSION;
00163 
00164                      rc = LDAP_OPT_SUCCESS;
00165                      break;
00166               } break;
00167 
00168        case LDAP_OPT_DESC:
00169               if( ld == NULL || ld->ld_sb == NULL ) {
00170                      /* bad param */
00171                      break;
00172               } 
00173 
00174               ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, outvalue );
00175               rc = LDAP_OPT_SUCCESS;
00176               break;
00177 
00178        case LDAP_OPT_SOCKBUF:
00179               if( ld == NULL ) break;
00180               *(Sockbuf **)outvalue = ld->ld_sb;
00181               rc = LDAP_OPT_SUCCESS;
00182               break;
00183 
00184        case LDAP_OPT_TIMEOUT:
00185               /* the caller has to free outvalue ! */
00186               if ( lo->ldo_tm_api.tv_sec < 0 ) {
00187                      *(void **)outvalue = NULL;
00188               } else if ( ldap_int_timeval_dup( outvalue, &lo->ldo_tm_api ) != 0 ) {
00189                      break; /* LDAP_OPT_ERROR */
00190               }
00191               rc = LDAP_OPT_SUCCESS;
00192               break;
00193               
00194        case LDAP_OPT_NETWORK_TIMEOUT:
00195               /* the caller has to free outvalue ! */
00196               if ( lo->ldo_tm_net.tv_sec < 0 ) {
00197                      *(void **)outvalue = NULL;
00198               } else if ( ldap_int_timeval_dup( outvalue, &lo->ldo_tm_net ) != 0 ) {
00199                      break; /* LDAP_OPT_ERROR */
00200               }
00201               rc = LDAP_OPT_SUCCESS;
00202               break;
00203 
00204        case LDAP_OPT_DEREF:
00205               * (int *) outvalue = lo->ldo_deref;
00206               rc = LDAP_OPT_SUCCESS;
00207               break;
00208 
00209        case LDAP_OPT_SIZELIMIT:
00210               * (int *) outvalue = lo->ldo_sizelimit;
00211               rc = LDAP_OPT_SUCCESS;
00212               break;
00213 
00214        case LDAP_OPT_TIMELIMIT:
00215               * (int *) outvalue = lo->ldo_timelimit;
00216               rc = LDAP_OPT_SUCCESS;
00217               break;
00218 
00219        case LDAP_OPT_REFERRALS:
00220               * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_REFERRALS);
00221               rc = LDAP_OPT_SUCCESS;
00222               break;
00223               
00224        case LDAP_OPT_RESTART:
00225               * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_RESTART);
00226               rc = LDAP_OPT_SUCCESS;
00227               break;
00228 
00229        case LDAP_OPT_PROTOCOL_VERSION:
00230               * (int *) outvalue = lo->ldo_version;
00231               rc = LDAP_OPT_SUCCESS;
00232               break;
00233 
00234        case LDAP_OPT_SERVER_CONTROLS:
00235               * (LDAPControl ***) outvalue =
00236                      ldap_controls_dup( lo->ldo_sctrls );
00237               rc = LDAP_OPT_SUCCESS;
00238               break;
00239 
00240        case LDAP_OPT_CLIENT_CONTROLS:
00241               * (LDAPControl ***) outvalue =
00242                      ldap_controls_dup( lo->ldo_cctrls );
00243               rc = LDAP_OPT_SUCCESS;
00244               break;
00245 
00246        case LDAP_OPT_HOST_NAME:
00247               * (char **) outvalue = ldap_url_list2hosts(lo->ldo_defludp);
00248               rc = LDAP_OPT_SUCCESS;
00249               break;
00250 
00251        case LDAP_OPT_URI:
00252               * (char **) outvalue = ldap_url_list2urls(lo->ldo_defludp);
00253               rc = LDAP_OPT_SUCCESS;
00254               break;
00255 
00256        case LDAP_OPT_DEFBASE:
00257               if( lo->ldo_defbase == NULL ) {
00258                      * (char **) outvalue = NULL;
00259               } else {
00260                      * (char **) outvalue = LDAP_STRDUP(lo->ldo_defbase);
00261               }
00262               rc = LDAP_OPT_SUCCESS;
00263               break;
00264 
00265        case LDAP_OPT_CONNECT_ASYNC:
00266               * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_CONNECT_ASYNC);
00267               rc = LDAP_OPT_SUCCESS;
00268               break;
00269 
00270        case LDAP_OPT_CONNECT_CB:
00271               {
00272                      /* Getting deletes the specified callback */
00273                      ldaplist **ll = &lo->ldo_conn_cbs;
00274                      for (;*ll;ll = &(*ll)->ll_next) {
00275                             if ((*ll)->ll_data == outvalue) {
00276                                    ldaplist *lc = *ll;
00277                                    *ll = lc->ll_next;
00278                                    LDAP_FREE(lc);
00279                                    break;
00280                             }
00281                      }
00282               }
00283               rc = LDAP_OPT_SUCCESS;
00284               break;
00285 
00286        case LDAP_OPT_RESULT_CODE:
00287               if(ld == NULL) {
00288                      /* bad param */
00289                      break;
00290               } 
00291               * (int *) outvalue = ld->ld_errno;
00292               rc = LDAP_OPT_SUCCESS;
00293               break;
00294 
00295        case LDAP_OPT_DIAGNOSTIC_MESSAGE:
00296               if(ld == NULL) {
00297                      /* bad param */
00298                      break;
00299               } 
00300 
00301               if( ld->ld_error == NULL ) {
00302                      * (char **) outvalue = NULL;
00303               } else {
00304                      * (char **) outvalue = LDAP_STRDUP(ld->ld_error);
00305               }
00306               rc = LDAP_OPT_SUCCESS;
00307               break;
00308 
00309        case LDAP_OPT_MATCHED_DN:
00310               if(ld == NULL) {
00311                      /* bad param */
00312                      break;
00313               } 
00314 
00315               if( ld->ld_matched == NULL ) {
00316                      * (char **) outvalue = NULL;
00317               } else {
00318                      * (char **) outvalue = LDAP_STRDUP( ld->ld_matched );
00319               }
00320               rc = LDAP_OPT_SUCCESS;
00321               break;
00322 
00323        case LDAP_OPT_REFERRAL_URLS:
00324               if(ld == NULL) {
00325                      /* bad param */
00326                      break;
00327               } 
00328 
00329               if( ld->ld_referrals == NULL ) {
00330                      * (char ***) outvalue = NULL;
00331               } else {
00332                      * (char ***) outvalue = ldap_value_dup(ld->ld_referrals);
00333               }
00334               rc = LDAP_OPT_SUCCESS;
00335               break;
00336 
00337        case LDAP_OPT_API_FEATURE_INFO: {
00338                      LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue;
00339                      int i;
00340 
00341                      if(info == NULL)
00342                             break; /* LDAP_OPT_ERROR */
00343 
00344                      if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) {
00345                             /* api info version mismatch */
00346                             info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
00347                             break; /* LDAP_OPT_ERROR */
00348                      }
00349 
00350                      if(info->ldapaif_name == NULL)
00351                             break; /* LDAP_OPT_ERROR */
00352 
00353                      for(i=0; features[i].ldapaif_name != NULL; i++) {
00354                             if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) {
00355                                    info->ldapaif_version =
00356                                           features[i].ldapaif_version;
00357                                    rc = LDAP_OPT_SUCCESS;
00358                                    break;
00359                             }
00360                      }
00361               }
00362               break;
00363 
00364        case LDAP_OPT_DEBUG_LEVEL:
00365               * (int *) outvalue = lo->ldo_debug;
00366               rc = LDAP_OPT_SUCCESS;
00367               break;
00368        
00369        case LDAP_OPT_SESSION_REFCNT:
00370               if(ld == NULL) {
00371                      /* bad param */
00372                      break;
00373               } 
00374               * (int *) outvalue = ld->ld_ldcrefcnt;
00375               rc = LDAP_OPT_SUCCESS;
00376               break;
00377 
00378        case LDAP_OPT_X_KEEPALIVE_IDLE:
00379               * (int *) outvalue = lo->ldo_keepalive_idle;
00380               rc = LDAP_OPT_SUCCESS;
00381               break;
00382 
00383        case LDAP_OPT_X_KEEPALIVE_PROBES:
00384               * (int *) outvalue = lo->ldo_keepalive_probes;
00385               rc = LDAP_OPT_SUCCESS;
00386               break;
00387 
00388        case LDAP_OPT_X_KEEPALIVE_INTERVAL:
00389               * (int *) outvalue = lo->ldo_keepalive_interval;
00390               rc = LDAP_OPT_SUCCESS;
00391               break;
00392 
00393        default:
00394 #ifdef HAVE_TLS
00395               if ( ldap_pvt_tls_get_option( ld, option, outvalue ) == 0 ) {
00396                      rc = LDAP_OPT_SUCCESS;
00397                      break;
00398               }
00399 #endif
00400 #ifdef HAVE_CYRUS_SASL
00401               if ( ldap_int_sasl_get_option( ld, option, outvalue ) == 0 ) {
00402                      rc = LDAP_OPT_SUCCESS;
00403                      break;
00404               }
00405 #endif
00406 #ifdef HAVE_GSSAPI
00407               if ( ldap_int_gssapi_get_option( ld, option, outvalue ) == 0 ) {
00408                      rc = LDAP_OPT_SUCCESS;
00409                      break;
00410               }
00411 #endif
00412               /* bad param */
00413               break;
00414        }
00415 
00416        LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
00417        return ( rc );
00418 }
00419 
00420 int
00421 ldap_set_option(
00422        LDAP   *ld,
00423        int           option,
00424        LDAP_CONST void      *invalue)
00425 {
00426        struct ldapoptions *lo;
00427        int *dbglvl = NULL;
00428        int rc = LDAP_OPT_ERROR;
00429 
00430        /* Get pointer to global option structure */
00431        lo = LDAP_INT_GLOBAL_OPT();
00432        if (lo == NULL)      {
00433               return LDAP_NO_MEMORY;
00434        }
00435 
00436        /*
00437         * The architecture to turn on debugging has a chicken and egg
00438         * problem. Thus, we introduce a fix here.
00439         */
00440 
00441        if (option == LDAP_OPT_DEBUG_LEVEL) {
00442               dbglvl = (int *) invalue;
00443        }
00444 
00445        if( lo->ldo_valid != LDAP_INITIALIZED ) {
00446               ldap_int_initialize(lo, dbglvl);
00447        }
00448 
00449        if(ld != NULL) {
00450               assert( LDAP_VALID( ld ) );
00451 
00452               if( !LDAP_VALID( ld ) ) {
00453                      return LDAP_OPT_ERROR;
00454               }
00455 
00456               lo = &ld->ld_options;
00457        }
00458 
00459        LDAP_MUTEX_LOCK( &lo->ldo_mutex );
00460 
00461        switch ( option ) {
00462 
00463        /* options with boolean values */
00464        case LDAP_OPT_REFERRALS:
00465               if(invalue == LDAP_OPT_OFF) {
00466                      LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS);
00467               } else {
00468                      LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS);
00469               }
00470               rc = LDAP_OPT_SUCCESS;
00471               break;
00472 
00473        case LDAP_OPT_RESTART:
00474               if(invalue == LDAP_OPT_OFF) {
00475                      LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART);
00476               } else {
00477                      LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART);
00478               }
00479               rc = LDAP_OPT_SUCCESS;
00480               break;
00481 
00482        case LDAP_OPT_CONNECT_ASYNC:
00483               if(invalue == LDAP_OPT_OFF) {
00484                      LDAP_BOOL_CLR(lo, LDAP_BOOL_CONNECT_ASYNC);
00485               } else {
00486                      LDAP_BOOL_SET(lo, LDAP_BOOL_CONNECT_ASYNC);
00487               }
00488               rc = LDAP_OPT_SUCCESS;
00489               break;
00490 
00491        /* options which can withstand invalue == NULL */
00492        case LDAP_OPT_SERVER_CONTROLS: {
00493                      LDAPControl *const *controls =
00494                             (LDAPControl *const *) invalue;
00495 
00496                      if( lo->ldo_sctrls )
00497                             ldap_controls_free( lo->ldo_sctrls );
00498 
00499                      if( controls == NULL || *controls == NULL ) {
00500                             lo->ldo_sctrls = NULL;
00501                             rc = LDAP_OPT_SUCCESS;
00502                             break;
00503                      }
00504                             
00505                      lo->ldo_sctrls = ldap_controls_dup( controls );
00506 
00507                      if(lo->ldo_sctrls == NULL) {
00508                             /* memory allocation error ? */
00509                             break; /* LDAP_OPT_ERROR */
00510                      }
00511               }
00512               rc = LDAP_OPT_SUCCESS;
00513               break;
00514 
00515        case LDAP_OPT_CLIENT_CONTROLS: {
00516                      LDAPControl *const *controls =
00517                             (LDAPControl *const *) invalue;
00518 
00519                      if( lo->ldo_cctrls )
00520                             ldap_controls_free( lo->ldo_cctrls );
00521 
00522                      if( controls == NULL || *controls == NULL ) {
00523                             lo->ldo_cctrls = NULL;
00524                             rc = LDAP_OPT_SUCCESS;
00525                             break;
00526                      }
00527                             
00528                      lo->ldo_cctrls = ldap_controls_dup( controls );
00529 
00530                      if(lo->ldo_cctrls == NULL) {
00531                             /* memory allocation error ? */
00532                             break; /* LDAP_OPT_ERROR */
00533                      }
00534               }
00535               rc = LDAP_OPT_SUCCESS;
00536               break;
00537 
00538 
00539        case LDAP_OPT_HOST_NAME: {
00540                      const char *host = (const char *) invalue;
00541                      LDAPURLDesc *ludlist = NULL;
00542                      rc = LDAP_OPT_SUCCESS;
00543 
00544                      if(host != NULL) {
00545                             rc = ldap_url_parsehosts( &ludlist, host,
00546                                    lo->ldo_defport ? lo->ldo_defport : LDAP_PORT );
00547 
00548                      } else if(ld == NULL) {
00549                             /*
00550                              * must want global default returned
00551                              * to initial condition.
00552                              */
00553                             rc = ldap_url_parselist_ext(&ludlist, "ldap://localhost/", NULL,
00554                                    LDAP_PVT_URL_PARSE_NOEMPTY_HOST
00555                                    | LDAP_PVT_URL_PARSE_DEF_PORT );
00556 
00557                      } else {
00558                             /*
00559                              * must want the session default
00560                              *   updated to the current global default
00561                              */
00562                             ludlist = ldap_url_duplist(
00563                                    ldap_int_global_options.ldo_defludp);
00564                             if (ludlist == NULL)
00565                                    rc = LDAP_NO_MEMORY;
00566                      }
00567 
00568                      if (rc == LDAP_OPT_SUCCESS) {
00569                             if (lo->ldo_defludp != NULL)
00570                                    ldap_free_urllist(lo->ldo_defludp);
00571                             lo->ldo_defludp = ludlist;
00572                      }
00573                      break;
00574               }
00575 
00576        case LDAP_OPT_URI: {
00577                      const char *urls = (const char *) invalue;
00578                      LDAPURLDesc *ludlist = NULL;
00579                      rc = LDAP_OPT_SUCCESS;
00580 
00581                      if(urls != NULL) {
00582                             rc = ldap_url_parselist_ext(&ludlist, urls, NULL,
00583                                    LDAP_PVT_URL_PARSE_NOEMPTY_HOST
00584                                    | LDAP_PVT_URL_PARSE_DEF_PORT );
00585                      } else if(ld == NULL) {
00586                             /*
00587                              * must want global default returned
00588                              * to initial condition.
00589                              */
00590                             rc = ldap_url_parselist_ext(&ludlist, "ldap://localhost/", NULL,
00591                                    LDAP_PVT_URL_PARSE_NOEMPTY_HOST
00592                                    | LDAP_PVT_URL_PARSE_DEF_PORT );
00593 
00594                      } else {
00595                             /*
00596                              * must want the session default
00597                              *   updated to the current global default
00598                              */
00599                             ludlist = ldap_url_duplist(
00600                                    ldap_int_global_options.ldo_defludp);
00601                             if (ludlist == NULL)
00602                                    rc = LDAP_URL_ERR_MEM;
00603                      }
00604 
00605                      switch (rc) {
00606                      case LDAP_URL_SUCCESS:             /* Success */
00607                             rc = LDAP_SUCCESS;
00608                             break;
00609 
00610                      case LDAP_URL_ERR_MEM:             /* can't allocate memory space */
00611                             rc = LDAP_NO_MEMORY;
00612                             break;
00613 
00614                      case LDAP_URL_ERR_PARAM:    /* parameter is bad */
00615                      case LDAP_URL_ERR_BADSCHEME:       /* URL doesn't begin with "ldap[si]://" */
00616                      case LDAP_URL_ERR_BADENCLOSURE:    /* URL is missing trailing ">" */
00617                      case LDAP_URL_ERR_BADURL:   /* URL is bad */
00618                      case LDAP_URL_ERR_BADHOST:  /* host port is bad */
00619                      case LDAP_URL_ERR_BADATTRS: /* bad (or missing) attributes */
00620                      case LDAP_URL_ERR_BADSCOPE: /* scope string is invalid (or missing) */
00621                      case LDAP_URL_ERR_BADFILTER:       /* bad or missing filter */
00622                      case LDAP_URL_ERR_BADEXTS:  /* bad or missing extensions */
00623                             rc = LDAP_PARAM_ERROR;
00624                             break;
00625                      }
00626 
00627                      if (rc == LDAP_SUCCESS) {
00628                             if (lo->ldo_defludp != NULL)
00629                                    ldap_free_urllist(lo->ldo_defludp);
00630                             lo->ldo_defludp = ludlist;
00631                      }
00632                      break;
00633               }
00634 
00635        case LDAP_OPT_DEFBASE: {
00636                      const char *newbase = (const char *) invalue;
00637                      char *defbase = NULL;
00638 
00639                      if ( newbase != NULL ) {
00640                             defbase = LDAP_STRDUP( newbase );
00641                             if ( defbase == NULL ) {
00642                                    rc = LDAP_NO_MEMORY;
00643                                    break;
00644                             }
00645 
00646                      } else if ( ld != NULL ) {
00647                             defbase = LDAP_STRDUP( ldap_int_global_options.ldo_defbase );
00648                             if ( defbase == NULL ) {
00649                                    rc = LDAP_NO_MEMORY;
00650                                    break;
00651                             }
00652                      }
00653                      
00654                      if ( lo->ldo_defbase != NULL )
00655                             LDAP_FREE( lo->ldo_defbase );
00656                      lo->ldo_defbase = defbase;
00657               }
00658               rc = LDAP_OPT_SUCCESS;
00659               break;
00660 
00661        case LDAP_OPT_DIAGNOSTIC_MESSAGE: {
00662                      const char *err = (const char *) invalue;
00663 
00664                      if(ld == NULL) {
00665                             /* need a struct ldap */
00666                             break; /* LDAP_OPT_ERROR */
00667                      }
00668 
00669                      if( ld->ld_error ) {
00670                             LDAP_FREE(ld->ld_error);
00671                             ld->ld_error = NULL;
00672                      }
00673 
00674                      if ( err ) {
00675                             ld->ld_error = LDAP_STRDUP(err);
00676                      }
00677               }
00678               rc = LDAP_OPT_SUCCESS;
00679               break;
00680 
00681        case LDAP_OPT_MATCHED_DN: {
00682                      const char *matched = (const char *) invalue;
00683 
00684                      if (ld == NULL) {
00685                             /* need a struct ldap */
00686                             break; /* LDAP_OPT_ERROR */
00687                      }
00688 
00689                      if( ld->ld_matched ) {
00690                             LDAP_FREE(ld->ld_matched);
00691                             ld->ld_matched = NULL;
00692                      }
00693 
00694                      if ( matched ) {
00695                             ld->ld_matched = LDAP_STRDUP( matched );
00696                      }
00697               }
00698               rc = LDAP_OPT_SUCCESS;
00699               break;
00700 
00701        case LDAP_OPT_REFERRAL_URLS: {
00702                      char *const *referrals = (char *const *) invalue;
00703                      
00704                      if(ld == NULL) {
00705                             /* need a struct ldap */
00706                             break; /* LDAP_OPT_ERROR */
00707                      }
00708 
00709                      if( ld->ld_referrals ) {
00710                             LDAP_VFREE(ld->ld_referrals);
00711                      }
00712 
00713                      if ( referrals ) {
00714                             ld->ld_referrals = ldap_value_dup(referrals);
00715                      }
00716               }
00717               rc = LDAP_OPT_SUCCESS;
00718               break;
00719 
00720        /* Only accessed from inside this function by ldap_set_rebind_proc() */
00721        case LDAP_OPT_REBIND_PROC: {
00722                      lo->ldo_rebind_proc = (LDAP_REBIND_PROC *)invalue;             
00723               }
00724               rc = LDAP_OPT_SUCCESS;
00725               break;
00726        case LDAP_OPT_REBIND_PARAMS: {
00727                      lo->ldo_rebind_params = (void *)invalue;         
00728               }
00729               rc = LDAP_OPT_SUCCESS;
00730               break;
00731 
00732        /* Only accessed from inside this function by ldap_set_nextref_proc() */
00733        case LDAP_OPT_NEXTREF_PROC: {
00734                      lo->ldo_nextref_proc = (LDAP_NEXTREF_PROC *)invalue;           
00735               }
00736               rc = LDAP_OPT_SUCCESS;
00737               break;
00738        case LDAP_OPT_NEXTREF_PARAMS: {
00739                      lo->ldo_nextref_params = (void *)invalue;        
00740               }
00741               rc = LDAP_OPT_SUCCESS;
00742               break;
00743 
00744        /* Only accessed from inside this function by ldap_set_urllist_proc() */
00745        case LDAP_OPT_URLLIST_PROC: {
00746                      lo->ldo_urllist_proc = (LDAP_URLLIST_PROC *)invalue;           
00747               }
00748               rc = LDAP_OPT_SUCCESS;
00749               break;
00750        case LDAP_OPT_URLLIST_PARAMS: {
00751                      lo->ldo_urllist_params = (void *)invalue;        
00752               }
00753               rc = LDAP_OPT_SUCCESS;
00754               break;
00755 
00756        /* read-only options */
00757        case LDAP_OPT_API_INFO:
00758        case LDAP_OPT_DESC:
00759        case LDAP_OPT_SOCKBUF:
00760        case LDAP_OPT_API_FEATURE_INFO:
00761               break; /* LDAP_OPT_ERROR */
00762 
00763        /* options which cannot withstand invalue == NULL */
00764        case LDAP_OPT_DEREF:
00765        case LDAP_OPT_SIZELIMIT:
00766        case LDAP_OPT_TIMELIMIT:
00767        case LDAP_OPT_PROTOCOL_VERSION:
00768        case LDAP_OPT_RESULT_CODE:
00769        case LDAP_OPT_DEBUG_LEVEL:
00770        case LDAP_OPT_TIMEOUT:
00771        case LDAP_OPT_NETWORK_TIMEOUT:
00772        case LDAP_OPT_CONNECT_CB:
00773        case LDAP_OPT_X_KEEPALIVE_IDLE:
00774        case LDAP_OPT_X_KEEPALIVE_PROBES :
00775        case LDAP_OPT_X_KEEPALIVE_INTERVAL :
00776               if(invalue == NULL) {
00777                      /* no place to set from */
00778                      LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
00779                      return ( LDAP_OPT_ERROR );
00780               }
00781               break;
00782 
00783        default:
00784 #ifdef HAVE_TLS
00785               if ( ldap_pvt_tls_set_option( ld, option, (void *)invalue ) == 0 ) {
00786                      LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
00787                      return ( LDAP_OPT_SUCCESS );
00788               }
00789 #endif
00790 #ifdef HAVE_CYRUS_SASL
00791               if ( ldap_int_sasl_set_option( ld, option, (void *)invalue ) == 0 ) {
00792                      LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
00793                      return ( LDAP_OPT_SUCCESS );
00794               }
00795 #endif
00796 #ifdef HAVE_GSSAPI
00797               if ( ldap_int_gssapi_set_option( ld, option, (void *)invalue ) == 0 ) {
00798                      LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
00799                      return ( LDAP_OPT_SUCCESS );
00800               }
00801 #endif
00802               /* bad param */
00803               break; /* LDAP_OPT_ERROR */
00804        }
00805 
00806        /* options which cannot withstand invalue == NULL */
00807 
00808        switch(option) {
00809        case LDAP_OPT_DEREF:
00810               /* FIXME: check value for protocol compliance? */
00811               lo->ldo_deref = * (const int *) invalue;
00812               rc = LDAP_OPT_SUCCESS;
00813               break;
00814 
00815        case LDAP_OPT_SIZELIMIT:
00816               /* FIXME: check value for protocol compliance? */
00817               lo->ldo_sizelimit = * (const int *) invalue;
00818               rc = LDAP_OPT_SUCCESS;
00819               break;
00820 
00821        case LDAP_OPT_TIMELIMIT:
00822               /* FIXME: check value for protocol compliance? */
00823               lo->ldo_timelimit = * (const int *) invalue;
00824               rc = LDAP_OPT_SUCCESS;
00825               break;
00826 
00827        case LDAP_OPT_TIMEOUT: {
00828                      const struct timeval *tv = 
00829                             (const struct timeval *) invalue;
00830 
00831                      lo->ldo_tm_api = *tv;
00832               }
00833               rc = LDAP_OPT_SUCCESS;
00834               break;
00835 
00836        case LDAP_OPT_NETWORK_TIMEOUT: {
00837                      const struct timeval *tv = 
00838                             (const struct timeval *) invalue;
00839 
00840                      lo->ldo_tm_net = *tv;
00841               }
00842               rc = LDAP_OPT_SUCCESS;
00843               break;
00844 
00845        case LDAP_OPT_PROTOCOL_VERSION: {
00846                      int vers = * (const int *) invalue;
00847                      if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) {
00848                             /* not supported */
00849                             break;
00850                      }
00851                      lo->ldo_version = vers;
00852               }
00853               rc = LDAP_OPT_SUCCESS;
00854               break;
00855 
00856        case LDAP_OPT_RESULT_CODE: {
00857                      int err = * (const int *) invalue;
00858 
00859                      if(ld == NULL) {
00860                             /* need a struct ldap */
00861                             break;
00862                      }
00863 
00864                      ld->ld_errno = err;
00865               }
00866               rc = LDAP_OPT_SUCCESS;
00867               break;
00868 
00869        case LDAP_OPT_DEBUG_LEVEL:
00870               lo->ldo_debug = * (const int *) invalue;
00871               rc = LDAP_OPT_SUCCESS;
00872               break;
00873 
00874        case LDAP_OPT_CONNECT_CB:
00875               {
00876                      /* setting pushes the callback */
00877                      ldaplist *ll;
00878                      ll = LDAP_MALLOC( sizeof( *ll ));
00879                      ll->ll_data = (void *)invalue;
00880                      ll->ll_next = lo->ldo_conn_cbs;
00881                      lo->ldo_conn_cbs = ll;
00882               }
00883               rc = LDAP_OPT_SUCCESS;
00884               break;
00885        case LDAP_OPT_X_KEEPALIVE_IDLE:
00886               lo->ldo_keepalive_idle = * (const int *) invalue;
00887               rc = LDAP_OPT_SUCCESS;
00888               break;
00889        case LDAP_OPT_X_KEEPALIVE_PROBES :
00890               lo->ldo_keepalive_probes = * (const int *) invalue;
00891               rc = LDAP_OPT_SUCCESS;
00892               break;
00893        case LDAP_OPT_X_KEEPALIVE_INTERVAL :
00894               lo->ldo_keepalive_interval = * (const int *) invalue;
00895               rc = LDAP_OPT_SUCCESS;
00896               break;
00897        
00898        }
00899        LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
00900        return ( rc );
00901 }
00902 
00903 int
00904 ldap_set_rebind_proc( LDAP *ld, LDAP_REBIND_PROC *proc, void *params )
00905 {
00906        int rc;
00907        rc = ldap_set_option( ld, LDAP_OPT_REBIND_PROC, (void *)proc );
00908        if( rc != LDAP_OPT_SUCCESS ) return rc;
00909 
00910        rc = ldap_set_option( ld, LDAP_OPT_REBIND_PARAMS, (void *)params );
00911        return rc;
00912 }
00913 
00914 int
00915 ldap_set_nextref_proc( LDAP *ld, LDAP_NEXTREF_PROC *proc, void *params )
00916 {
00917        int rc;
00918        rc = ldap_set_option( ld, LDAP_OPT_NEXTREF_PROC, (void *)proc );
00919        if( rc != LDAP_OPT_SUCCESS ) return rc;
00920 
00921        rc = ldap_set_option( ld, LDAP_OPT_NEXTREF_PARAMS, (void *)params );
00922        return rc;
00923 }
00924 
00925 int
00926 ldap_set_urllist_proc( LDAP *ld, LDAP_URLLIST_PROC *proc, void *params )
00927 {
00928        int rc;
00929        rc = ldap_set_option( ld, LDAP_OPT_URLLIST_PROC, (void *)proc );
00930        if( rc != LDAP_OPT_SUCCESS ) return rc;
00931 
00932        rc = ldap_set_option( ld, LDAP_OPT_URLLIST_PARAMS, (void *)params );
00933        return rc;
00934 }