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