]> git.sur5r.net Git - openldap/blob - libraries/libldap/options.c
cfc4711eb10a51b407efb9be394c54c7e931bf17
[openldap] / libraries / libldap / options.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2006 The OpenLDAP Foundation.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted only as authorized by the OpenLDAP
9  * Public License.
10  *
11  * A copy of this license is available in the file LICENSE in the
12  * top-level directory of the distribution or, alternatively, at
13  * <http://www.OpenLDAP.org/license.html>.
14  */
15
16 #include "portable.h"
17
18 #include <stdio.h>
19
20 #include <ac/stdlib.h>
21
22 #include <ac/socket.h>
23 #include <ac/string.h>
24 #include <ac/time.h>
25
26 #include "ldap-int.h"
27
28 #define LDAP_OPT_REBIND_PROC 0x4e814d
29 #define LDAP_OPT_REBIND_PARAMS 0x4e814e
30
31 #define LDAP_OPT_NEXTREF_PROC 0x4e815d
32 #define LDAP_OPT_NEXTREF_PARAMS 0x4e815e
33
34 static const LDAPAPIFeatureInfo features[] = {
35 #ifdef LDAP_API_FEATURE_X_OPENLDAP
36         {       /* OpenLDAP Extensions API Feature */
37                 LDAP_FEATURE_INFO_VERSION,
38                 "X_OPENLDAP",
39                 LDAP_API_FEATURE_X_OPENLDAP
40         },
41 #endif
42
43 #ifdef LDAP_API_FEATURE_THREAD_SAFE
44         {       /* Basic Thread Safe */
45                 LDAP_FEATURE_INFO_VERSION,
46                 "THREAD_SAFE",
47                 LDAP_API_FEATURE_THREAD_SAFE
48         },
49 #endif
50 #ifdef LDAP_API_FEATURE_SESSION_THREAD_SAFE
51         {       /* Session Thread Safe */
52                 LDAP_FEATURE_INFO_VERSION,
53                 "SESSION_THREAD_SAFE",
54                 LDAP_API_FEATURE_SESSION_THREAD_SAFE
55         },
56 #endif
57 #ifdef LDAP_API_FEATURE_OPERATION_THREAD_SAFE
58         {       /* Operation Thread Safe */
59                 LDAP_FEATURE_INFO_VERSION,
60                 "OPERATION_THREAD_SAFE",
61                 LDAP_API_FEATURE_OPERATION_THREAD_SAFE
62         },
63 #endif
64 #ifdef LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
65         {       /* OpenLDAP Reentrant */
66                 LDAP_FEATURE_INFO_VERSION,
67                 "X_OPENLDAP_REENTRANT",
68                 LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
69         },
70 #endif
71 #if defined( LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE ) && \
72         defined( LDAP_THREAD_SAFE )
73         {       /* OpenLDAP Thread Safe */
74                 LDAP_FEATURE_INFO_VERSION,
75                 "X_OPENLDAP_THREAD_SAFE",
76                 LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE
77         },
78 #endif
79 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
80         {       /* V2 Referrals */
81                 LDAP_FEATURE_INFO_VERSION,
82                 "X_OPENLDAP_V2_REFERRALS",
83                 LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
84         },
85 #endif
86         {0, NULL, 0}
87 };
88
89 int
90 ldap_get_option(
91         LDAP    *ld,
92         int             option,
93         void    *outvalue)
94 {
95         struct ldapoptions *lo;
96
97         /* Get pointer to global option structure */
98         lo = LDAP_INT_GLOBAL_OPT();   
99         if (NULL == lo) {
100                 return LDAP_NO_MEMORY;
101         }
102
103         if( lo->ldo_valid != LDAP_INITIALIZED ) {
104                 ldap_int_initialize(lo, NULL);
105         }
106
107         if(ld != NULL) {
108                 assert( LDAP_VALID( ld ) );
109
110                 if( !LDAP_VALID( ld ) ) {
111                         return LDAP_OPT_ERROR;
112                 }
113
114                 lo = &ld->ld_options;
115         }
116
117         if(outvalue == NULL) {
118                 /* no place to get to */
119                 return LDAP_OPT_ERROR;
120         }
121
122         switch(option) {
123         case LDAP_OPT_API_INFO: {
124                         struct ldapapiinfo *info = (struct ldapapiinfo *) outvalue;
125
126                         if(info == NULL) {
127                                 /* outvalue must point to an apiinfo structure */
128                                 return LDAP_OPT_ERROR;
129                         }
130
131                         if(info->ldapai_info_version != LDAP_API_INFO_VERSION) {
132                                 /* api info version mismatch */
133                                 info->ldapai_info_version = LDAP_API_INFO_VERSION;
134                                 return LDAP_OPT_ERROR;
135                         }
136
137                         info->ldapai_api_version = LDAP_API_VERSION;
138                         info->ldapai_protocol_version = LDAP_VERSION_MAX;
139
140                         if(features[0].ldapaif_name == NULL) {
141                                 info->ldapai_extensions = NULL;
142                         } else {
143                                 int i;
144                                 info->ldapai_extensions = LDAP_MALLOC(sizeof(char *) *
145                                         sizeof(features)/sizeof(LDAPAPIFeatureInfo));
146
147                                 for(i=0; features[i].ldapaif_name != NULL; i++) {
148                                         info->ldapai_extensions[i] =
149                                                 LDAP_STRDUP(features[i].ldapaif_name);
150                                 }
151
152                                 info->ldapai_extensions[i] = NULL;
153                         }
154
155                         info->ldapai_vendor_name = LDAP_STRDUP(LDAP_VENDOR_NAME);
156                         info->ldapai_vendor_version = LDAP_VENDOR_VERSION;
157
158                         return LDAP_OPT_SUCCESS;
159                 } break;
160
161         case LDAP_OPT_DESC:
162                 if( ld == NULL || ld->ld_sb == NULL ) {
163                         /* bad param */
164                         break;
165                 } 
166
167                 ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, outvalue );
168                 return LDAP_OPT_SUCCESS;
169
170         case LDAP_OPT_SOCKBUF:
171                 if( ld == NULL ) break;
172                 *(Sockbuf **)outvalue = ld->ld_sb;
173                 return LDAP_OPT_SUCCESS;
174
175         case LDAP_OPT_TIMEOUT:
176                 /* the caller has to free outvalue ! */
177                 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_api) != 0 ) {
178                         return LDAP_OPT_ERROR;
179                 }
180                 return LDAP_OPT_SUCCESS;
181                 
182         case LDAP_OPT_NETWORK_TIMEOUT:
183                 /* the caller has to free outvalue ! */
184                 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_net ) != 0 ) {
185                         return LDAP_OPT_ERROR;
186                 }
187                 return LDAP_OPT_SUCCESS;
188
189         case LDAP_OPT_DEREF:
190                 * (int *) outvalue = lo->ldo_deref;
191                 return LDAP_OPT_SUCCESS;
192
193         case LDAP_OPT_SIZELIMIT:
194                 * (int *) outvalue = lo->ldo_sizelimit;
195                 return LDAP_OPT_SUCCESS;
196
197         case LDAP_OPT_TIMELIMIT:
198                 * (int *) outvalue = lo->ldo_timelimit;
199                 return LDAP_OPT_SUCCESS;
200
201         case LDAP_OPT_REFERRALS:
202                 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_REFERRALS);
203                 return LDAP_OPT_SUCCESS;
204                 
205         case LDAP_OPT_RESTART:
206                 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_RESTART);
207                 return LDAP_OPT_SUCCESS;
208
209         case LDAP_OPT_PROTOCOL_VERSION:
210                 * (int *) outvalue = lo->ldo_version;
211                 return LDAP_OPT_SUCCESS;
212
213         case LDAP_OPT_SERVER_CONTROLS:
214                 * (LDAPControl ***) outvalue =
215                         ldap_controls_dup( lo->ldo_sctrls );
216
217                 return LDAP_OPT_SUCCESS;
218
219         case LDAP_OPT_CLIENT_CONTROLS:
220                 * (LDAPControl ***) outvalue =
221                         ldap_controls_dup( lo->ldo_cctrls );
222
223                 return LDAP_OPT_SUCCESS;
224
225         case LDAP_OPT_HOST_NAME:
226                 * (char **) outvalue = ldap_url_list2hosts(lo->ldo_defludp);
227                 return LDAP_OPT_SUCCESS;
228
229         case LDAP_OPT_URI:
230                 * (char **) outvalue = ldap_url_list2urls(lo->ldo_defludp);
231                 return LDAP_OPT_SUCCESS;
232
233         case LDAP_OPT_DEFBASE:
234                 if( lo->ldo_defbase == NULL ) {
235                         * (char **) outvalue = NULL;
236                 } else {
237                         * (char **) outvalue = LDAP_STRDUP(lo->ldo_defbase);
238                 }
239
240                 return LDAP_OPT_SUCCESS;
241
242         case LDAP_OPT_ERROR_NUMBER:
243                 if(ld == NULL) {
244                         /* bad param */
245                         break;
246                 } 
247                 * (int *) outvalue = ld->ld_errno;
248                 return LDAP_OPT_SUCCESS;
249
250         case LDAP_OPT_ERROR_STRING:
251                 if(ld == NULL) {
252                         /* bad param */
253                         break;
254                 } 
255
256                 if( ld->ld_error == NULL ) {
257                         * (char **) outvalue = NULL;
258                 } else {
259                         * (char **) outvalue = LDAP_STRDUP(ld->ld_error);
260                 }
261
262                 return LDAP_OPT_SUCCESS;
263
264         case LDAP_OPT_MATCHED_DN:
265                 if(ld == NULL) {
266                         /* bad param */
267                         break;
268                 } 
269
270                 if( ld->ld_matched == NULL ) {
271                         * (char **) outvalue = NULL;
272                 } else {
273                         * (char **) outvalue = LDAP_STRDUP( ld->ld_matched );
274                 }
275
276                 return LDAP_OPT_SUCCESS;
277
278         case LDAP_OPT_REFERRAL_URLS:
279                 if(ld == NULL) {
280                         /* bad param */
281                         break;
282                 } 
283
284                 if( ld->ld_referrals == NULL ) {
285                         * (char ***) outvalue = NULL;
286                 } else {
287                         * (char ***) outvalue = ldap_value_dup(ld->ld_referrals);
288                 }
289
290                 return LDAP_OPT_SUCCESS;
291
292         case LDAP_OPT_API_FEATURE_INFO: {
293                         LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue;
294                         int i;
295
296                         if(info == NULL) return LDAP_OPT_ERROR;
297
298                         if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) {
299                                 /* api info version mismatch */
300                                 info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
301                                 return LDAP_OPT_ERROR;
302                         }
303
304                         if(info->ldapaif_name == NULL) return LDAP_OPT_ERROR;
305
306                         for(i=0; features[i].ldapaif_name != NULL; i++) {
307                                 if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) {
308                                         info->ldapaif_version =
309                                                 features[i].ldapaif_version;
310                                         return LDAP_OPT_SUCCESS;
311                                 }
312                         }
313                 }
314                 break;
315
316         case LDAP_OPT_DEBUG_LEVEL:
317                 * (int *) outvalue = lo->ldo_debug;
318                 return LDAP_OPT_SUCCESS;
319
320         default:
321 #ifdef HAVE_TLS
322                 if ( ldap_pvt_tls_get_option( ld, option, outvalue ) == 0 ) {
323                         return LDAP_OPT_SUCCESS;
324                 }
325 #endif
326 #ifdef HAVE_CYRUS_SASL
327                 if ( ldap_int_sasl_get_option( ld, option, outvalue ) == 0 ) {
328                         return LDAP_OPT_SUCCESS;
329                 }
330 #endif
331                 /* bad param */
332                 break;
333         }
334
335         return LDAP_OPT_ERROR;
336 }
337
338 int
339 ldap_set_option(
340         LDAP    *ld,
341         int             option,
342         LDAP_CONST void *invalue)
343 {
344         struct ldapoptions *lo;
345         int *dbglvl = NULL;
346
347         /* Get pointer to global option structure */
348         lo = LDAP_INT_GLOBAL_OPT();
349         if (lo == NULL) {
350                 return LDAP_NO_MEMORY;
351         }
352
353         /*
354          * The architecture to turn on debugging has a chicken and egg
355          * problem. Thus, we introduce a fix here.
356          */
357
358         if (option == LDAP_OPT_DEBUG_LEVEL) {
359                 dbglvl = (int *) invalue;
360         }
361
362         if( lo->ldo_valid != LDAP_INITIALIZED ) {
363                 ldap_int_initialize(lo, dbglvl);
364         }
365
366         if(ld != NULL) {
367                 assert( LDAP_VALID( ld ) );
368
369                 if( !LDAP_VALID( ld ) ) {
370                         return LDAP_OPT_ERROR;
371                 }
372
373                 lo = &ld->ld_options;
374         }
375
376         switch(option) {
377         case LDAP_OPT_REFERRALS:
378                 if(invalue == LDAP_OPT_OFF) {
379                         LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS);
380                 } else {
381                         LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS);
382                 }
383                 return LDAP_OPT_SUCCESS;
384
385         case LDAP_OPT_RESTART:
386                 if(invalue == LDAP_OPT_OFF) {
387                         LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART);
388                 } else {
389                         LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART);
390                 }
391                 return LDAP_OPT_SUCCESS;
392         }
393
394         /* options which can withstand invalue == NULL */
395         switch ( option ) {
396         case LDAP_OPT_SERVER_CONTROLS: {
397                         LDAPControl *const *controls =
398                                 (LDAPControl *const *) invalue;
399
400                         if( lo->ldo_sctrls )
401                                 ldap_controls_free( lo->ldo_sctrls );
402
403                         if( controls == NULL || *controls == NULL ) {
404                                 lo->ldo_sctrls = NULL;
405                                 return LDAP_OPT_SUCCESS;
406                         }
407                                 
408                         lo->ldo_sctrls = ldap_controls_dup( controls );
409
410                         if(lo->ldo_sctrls == NULL) {
411                                 /* memory allocation error ? */
412                                 break;
413                         }
414                 } return LDAP_OPT_SUCCESS;
415
416         case LDAP_OPT_CLIENT_CONTROLS: {
417                         LDAPControl *const *controls =
418                                 (LDAPControl *const *) invalue;
419
420                         if( lo->ldo_cctrls )
421                                 ldap_controls_free( lo->ldo_cctrls );
422
423                         if( controls == NULL || *controls == NULL ) {
424                                 lo->ldo_cctrls = NULL;
425                                 return LDAP_OPT_SUCCESS;
426                         }
427                                 
428                         lo->ldo_cctrls = ldap_controls_dup( controls );
429
430                         if(lo->ldo_cctrls == NULL) {
431                                 /* memory allocation error ? */
432                                 break;
433                         }
434                 } return LDAP_OPT_SUCCESS;
435
436         case LDAP_OPT_TIMEOUT: {
437                         const struct timeval *tv = 
438                                 (const struct timeval *) invalue;
439
440                         if ( lo->ldo_tm_api != NULL ) {
441                                 LDAP_FREE( lo->ldo_tm_api );
442                                 lo->ldo_tm_api = NULL;
443                         }
444
445                         if ( ldap_int_timeval_dup( &lo->ldo_tm_api, tv ) != 0 ) {
446                                 return LDAP_OPT_ERROR;
447                         }
448                 } return LDAP_OPT_SUCCESS;
449
450         case LDAP_OPT_NETWORK_TIMEOUT: {
451                         const struct timeval *tv = 
452                                 (const struct timeval *) invalue;
453
454                         if ( lo->ldo_tm_net != NULL ) {
455                                 LDAP_FREE( lo->ldo_tm_net );
456                                 lo->ldo_tm_net = NULL;
457                         }
458
459                         if ( ldap_int_timeval_dup( &lo->ldo_tm_net, tv ) != 0 ) {
460                                 return LDAP_OPT_ERROR;
461                         }
462                 } return LDAP_OPT_SUCCESS;
463
464         case LDAP_OPT_HOST_NAME: {
465                         const char *host = (const char *) invalue;
466                         LDAPURLDesc *ludlist = NULL;
467                         int rc = LDAP_OPT_SUCCESS;
468
469                         if(host != NULL) {
470                                 rc = ldap_url_parsehosts( &ludlist, host,
471                                         lo->ldo_defport ? lo->ldo_defport : LDAP_PORT );
472
473                         } else if(ld == NULL) {
474                                 /*
475                                  * must want global default returned
476                                  * to initial condition.
477                                  */
478                                 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
479
480                         } else {
481                                 /*
482                                  * must want the session default
483                                  *   updated to the current global default
484                                  */
485                                 ludlist = ldap_url_duplist(
486                                         ldap_int_global_options.ldo_defludp);
487                                 if (ludlist == NULL)
488                                         rc = LDAP_NO_MEMORY;
489                         }
490
491                         if (rc == LDAP_OPT_SUCCESS) {
492                                 if (lo->ldo_defludp != NULL)
493                                         ldap_free_urllist(lo->ldo_defludp);
494                                 lo->ldo_defludp = ludlist;
495                         }
496                         return rc;
497                 }
498
499         case LDAP_OPT_URI: {
500                         const char *urls = (const char *) invalue;
501                         LDAPURLDesc *ludlist = NULL;
502                         int rc = LDAP_OPT_SUCCESS;
503
504                         if(urls != NULL) {
505                                 rc = ldap_url_parselist(&ludlist, urls);
506                         } else if(ld == NULL) {
507                                 /*
508                                  * must want global default returned
509                                  * to initial condition.
510                                  */
511                                 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
512
513                         } else {
514                                 /*
515                                  * must want the session default
516                                  *   updated to the current global default
517                                  */
518                                 ludlist = ldap_url_duplist(
519                                         ldap_int_global_options.ldo_defludp);
520                                 if (ludlist == NULL)
521                                         rc = LDAP_URL_ERR_MEM;
522                         }
523
524                         switch (rc) {
525                         case LDAP_URL_SUCCESS:          /* Success */
526                                 rc = LDAP_SUCCESS;
527                                 break;
528
529                         case LDAP_URL_ERR_MEM:          /* can't allocate memory space */
530                                 rc = LDAP_NO_MEMORY;
531                                 break;
532
533                         case LDAP_URL_ERR_PARAM:        /* parameter is bad */
534                         case LDAP_URL_ERR_BADSCHEME:    /* URL doesn't begin with "ldap[si]://" */
535                         case LDAP_URL_ERR_BADENCLOSURE: /* URL is missing trailing ">" */
536                         case LDAP_URL_ERR_BADURL:       /* URL is bad */
537                         case LDAP_URL_ERR_BADHOST:      /* host port is bad */
538                         case LDAP_URL_ERR_BADATTRS:     /* bad (or missing) attributes */
539                         case LDAP_URL_ERR_BADSCOPE:     /* scope string is invalid (or missing) */
540                         case LDAP_URL_ERR_BADFILTER:    /* bad or missing filter */
541                         case LDAP_URL_ERR_BADEXTS:      /* bad or missing extensions */
542                                 rc = LDAP_PARAM_ERROR;
543                                 break;
544                         }
545
546                         if (rc == LDAP_SUCCESS) {
547                                 if (lo->ldo_defludp != NULL)
548                                         ldap_free_urllist(lo->ldo_defludp);
549                                 lo->ldo_defludp = ludlist;
550                         }
551                         return rc;
552                 }
553
554         case LDAP_OPT_DEFBASE: {
555                         const char *newbase = (const char *) invalue;
556                         char *defbase = NULL;
557
558                         if ( newbase != NULL ) {
559                                 defbase = LDAP_STRDUP( newbase );
560                                 if ( defbase == NULL ) return LDAP_NO_MEMORY;
561
562                         } else if ( ld != NULL ) {
563                                 defbase = LDAP_STRDUP( ldap_int_global_options.ldo_defbase );
564                                 if ( defbase == NULL ) return LDAP_NO_MEMORY;
565                         }
566                         
567                         if ( lo->ldo_defbase != NULL )
568                                 LDAP_FREE( lo->ldo_defbase );
569                         lo->ldo_defbase = defbase;
570                 } return LDAP_OPT_SUCCESS;
571
572         case LDAP_OPT_ERROR_STRING: {
573                         const char *err = (const char *) invalue;
574
575                         if(ld == NULL) {
576                                 /* need a struct ldap */
577                                 return LDAP_OPT_ERROR;
578                         }
579
580                         if( ld->ld_error ) {
581                                 LDAP_FREE(ld->ld_error);
582                                 ld->ld_error = NULL;
583                         }
584
585                         if ( err ) {
586                                 ld->ld_error = LDAP_STRDUP(err);
587                         }
588                 } return LDAP_OPT_SUCCESS;
589
590         case LDAP_OPT_MATCHED_DN: {
591                         const char *matched = (const char *) invalue;
592
593                         if (ld == NULL) {
594                                 /* need a struct ldap */
595                                 return LDAP_OPT_ERROR;
596                         }
597
598                         if( ld->ld_matched ) {
599                                 LDAP_FREE(ld->ld_matched);
600                                 ld->ld_matched = NULL;
601                         }
602
603                         if ( matched ) {
604                                 ld->ld_matched = LDAP_STRDUP( matched );
605                         }
606                 } return LDAP_OPT_SUCCESS;
607
608         case LDAP_OPT_REFERRAL_URLS: {
609                         char *const *referrals = (char *const *) invalue;
610                         
611                         if(ld == NULL) {
612                                 /* need a struct ldap */
613                                 return LDAP_OPT_ERROR;
614                         }
615
616                         if( ld->ld_referrals ) {
617                                 LDAP_VFREE(ld->ld_referrals);
618                         }
619
620                         if ( referrals ) {
621                                 ld->ld_referrals = ldap_value_dup(referrals);
622                         }
623                 } return LDAP_OPT_SUCCESS;
624
625         /* Only accessed from inside this function by ldap_set_rebind_proc() */
626         case LDAP_OPT_REBIND_PROC: {
627                         lo->ldo_rebind_proc = (LDAP_REBIND_PROC *)invalue;              
628                 } return LDAP_OPT_SUCCESS;
629         case LDAP_OPT_REBIND_PARAMS: {
630                         lo->ldo_rebind_params = (void *)invalue;                
631                 } return LDAP_OPT_SUCCESS;
632
633         /* Only accessed from inside this function by ldap_set_nextref_proc() */
634         case LDAP_OPT_NEXTREF_PROC: {
635                         lo->ldo_nextref_proc = (LDAP_NEXTREF_PROC *)invalue;            
636                 } return LDAP_OPT_SUCCESS;
637         case LDAP_OPT_NEXTREF_PARAMS: {
638                         lo->ldo_nextref_params = (void *)invalue;               
639                 } return LDAP_OPT_SUCCESS;
640
641         /* read-only options */
642         case LDAP_OPT_API_INFO:
643         case LDAP_OPT_DESC:
644         case LDAP_OPT_API_FEATURE_INFO:
645                 return LDAP_OPT_ERROR;
646
647         /* options which cannot withstand invalue == NULL */
648         case LDAP_OPT_DEREF:
649         case LDAP_OPT_SIZELIMIT:
650         case LDAP_OPT_TIMELIMIT:
651         case LDAP_OPT_PROTOCOL_VERSION:
652         case LDAP_OPT_ERROR_NUMBER:
653         case LDAP_OPT_DEBUG_LEVEL:
654                 if(invalue == NULL) {
655                         /* no place to set from */
656                         return LDAP_OPT_ERROR;
657                 }
658                 break;
659
660         default:
661 #ifdef HAVE_TLS
662                 if ( ldap_pvt_tls_set_option( ld, option, (void *)invalue ) == 0 )
663                         return LDAP_OPT_SUCCESS;
664 #endif
665 #ifdef HAVE_CYRUS_SASL
666                 if ( ldap_int_sasl_set_option( ld, option, (void *)invalue ) == 0 )
667                         return LDAP_OPT_SUCCESS;
668 #endif
669                 /* bad param */
670                 return LDAP_OPT_ERROR;
671         }
672
673         /* options which cannot withstand invalue == NULL */
674
675         switch(option) {
676         case LDAP_OPT_DEREF:
677                 lo->ldo_deref = * (const int *) invalue;
678                 return LDAP_OPT_SUCCESS;
679
680         case LDAP_OPT_SIZELIMIT:
681                 lo->ldo_sizelimit = * (const int *) invalue;
682                 return LDAP_OPT_SUCCESS;
683
684         case LDAP_OPT_TIMELIMIT:
685                 lo->ldo_timelimit = * (const int *) invalue;
686                 return LDAP_OPT_SUCCESS;
687
688         case LDAP_OPT_PROTOCOL_VERSION: {
689                         int vers = * (const int *) invalue;
690                         if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) {
691                                 /* not supported */
692                                 break;
693                         }
694                         lo->ldo_version = vers;
695                 } return LDAP_OPT_SUCCESS;
696
697         case LDAP_OPT_ERROR_NUMBER: {
698                         int err = * (const int *) invalue;
699
700                         if(ld == NULL) {
701                                 /* need a struct ldap */
702                                 break;
703                         }
704
705                         ld->ld_errno = err;
706                 } return LDAP_OPT_SUCCESS;
707
708         case LDAP_OPT_DEBUG_LEVEL:
709                 lo->ldo_debug = * (const int *) invalue;
710                 return LDAP_OPT_SUCCESS;
711         }
712         return LDAP_OPT_ERROR;
713 }
714
715 int
716 ldap_set_rebind_proc( LDAP *ld, LDAP_REBIND_PROC *proc, void *params )
717 {
718         int rc;
719         rc = ldap_set_option( ld, LDAP_OPT_REBIND_PROC, (void *)proc );
720         if( rc != LDAP_OPT_SUCCESS ) return rc;
721
722         rc = ldap_set_option( ld, LDAP_OPT_REBIND_PARAMS, (void *)params );
723         return rc;
724 }
725
726 int
727 ldap_set_nextref_proc( LDAP *ld, LDAP_NEXTREF_PROC *proc, void *params )
728 {
729         int rc;
730         rc = ldap_set_option( ld, LDAP_OPT_NEXTREF_PROC, (void *)proc );
731         if( rc != LDAP_OPT_SUCCESS ) return rc;
732
733         rc = ldap_set_option( ld, LDAP_OPT_NEXTREF_PARAMS, (void *)params );
734         return rc;
735 }