]> git.sur5r.net Git - openldap/blob - libraries/libldap/options.c
First cut to truly async connect:
[openldap] / libraries / libldap / options.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2007 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_CONNECT_ASYNC:
246                 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_CONNECT_ASYNC);
247                 return LDAP_OPT_SUCCESS;
248                 
249         case LDAP_OPT_RESULT_CODE:
250                 if(ld == NULL) {
251                         /* bad param */
252                         break;
253                 } 
254                 * (int *) outvalue = ld->ld_errno;
255                 return LDAP_OPT_SUCCESS;
256
257         case LDAP_OPT_DIAGNOSTIC_MESSAGE:
258                 if(ld == NULL) {
259                         /* bad param */
260                         break;
261                 } 
262
263                 if( ld->ld_error == NULL ) {
264                         * (char **) outvalue = NULL;
265                 } else {
266                         * (char **) outvalue = LDAP_STRDUP(ld->ld_error);
267                 }
268
269                 return LDAP_OPT_SUCCESS;
270
271         case LDAP_OPT_MATCHED_DN:
272                 if(ld == NULL) {
273                         /* bad param */
274                         break;
275                 } 
276
277                 if( ld->ld_matched == NULL ) {
278                         * (char **) outvalue = NULL;
279                 } else {
280                         * (char **) outvalue = LDAP_STRDUP( ld->ld_matched );
281                 }
282
283                 return LDAP_OPT_SUCCESS;
284
285         case LDAP_OPT_REFERRAL_URLS:
286                 if(ld == NULL) {
287                         /* bad param */
288                         break;
289                 } 
290
291                 if( ld->ld_referrals == NULL ) {
292                         * (char ***) outvalue = NULL;
293                 } else {
294                         * (char ***) outvalue = ldap_value_dup(ld->ld_referrals);
295                 }
296
297                 return LDAP_OPT_SUCCESS;
298
299         case LDAP_OPT_API_FEATURE_INFO: {
300                         LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue;
301                         int i;
302
303                         if(info == NULL) return LDAP_OPT_ERROR;
304
305                         if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) {
306                                 /* api info version mismatch */
307                                 info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
308                                 return LDAP_OPT_ERROR;
309                         }
310
311                         if(info->ldapaif_name == NULL) return LDAP_OPT_ERROR;
312
313                         for(i=0; features[i].ldapaif_name != NULL; i++) {
314                                 if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) {
315                                         info->ldapaif_version =
316                                                 features[i].ldapaif_version;
317                                         return LDAP_OPT_SUCCESS;
318                                 }
319                         }
320                 }
321                 break;
322
323         case LDAP_OPT_DEBUG_LEVEL:
324                 * (int *) outvalue = lo->ldo_debug;
325                 return LDAP_OPT_SUCCESS;
326
327         default:
328 #ifdef HAVE_TLS
329                 if ( ldap_pvt_tls_get_option( ld, option, outvalue ) == 0 ) {
330                         return LDAP_OPT_SUCCESS;
331                 }
332 #endif
333 #ifdef HAVE_CYRUS_SASL
334                 if ( ldap_int_sasl_get_option( ld, option, outvalue ) == 0 ) {
335                         return LDAP_OPT_SUCCESS;
336                 }
337 #endif
338                 /* bad param */
339                 break;
340         }
341
342         return LDAP_OPT_ERROR;
343 }
344
345 int
346 ldap_set_option(
347         LDAP    *ld,
348         int             option,
349         LDAP_CONST void *invalue)
350 {
351         struct ldapoptions *lo;
352         int *dbglvl = NULL;
353
354         /* Get pointer to global option structure */
355         lo = LDAP_INT_GLOBAL_OPT();
356         if (lo == NULL) {
357                 return LDAP_NO_MEMORY;
358         }
359
360         /*
361          * The architecture to turn on debugging has a chicken and egg
362          * problem. Thus, we introduce a fix here.
363          */
364
365         if (option == LDAP_OPT_DEBUG_LEVEL) {
366                 dbglvl = (int *) invalue;
367         }
368
369         if( lo->ldo_valid != LDAP_INITIALIZED ) {
370                 ldap_int_initialize(lo, dbglvl);
371         }
372
373         if(ld != NULL) {
374                 assert( LDAP_VALID( ld ) );
375
376                 if( !LDAP_VALID( ld ) ) {
377                         return LDAP_OPT_ERROR;
378                 }
379
380                 lo = &ld->ld_options;
381         }
382
383         switch(option) {
384         case LDAP_OPT_REFERRALS:
385                 if(invalue == LDAP_OPT_OFF) {
386                         LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS);
387                 } else {
388                         LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS);
389                 }
390                 return LDAP_OPT_SUCCESS;
391
392         case LDAP_OPT_RESTART:
393                 if(invalue == LDAP_OPT_OFF) {
394                         LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART);
395                 } else {
396                         LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART);
397                 }
398                 return LDAP_OPT_SUCCESS;
399
400         case LDAP_OPT_CONNECT_ASYNC:
401                 if(invalue == LDAP_OPT_OFF) {
402                         LDAP_BOOL_CLR(lo, LDAP_BOOL_CONNECT_ASYNC);
403                 } else {
404                         LDAP_BOOL_SET(lo, LDAP_BOOL_CONNECT_ASYNC);
405                 }
406                 return LDAP_OPT_SUCCESS;
407         }
408
409         /* options which can withstand invalue == NULL */
410         switch ( option ) {
411         case LDAP_OPT_SERVER_CONTROLS: {
412                         LDAPControl *const *controls =
413                                 (LDAPControl *const *) invalue;
414
415                         if( lo->ldo_sctrls )
416                                 ldap_controls_free( lo->ldo_sctrls );
417
418                         if( controls == NULL || *controls == NULL ) {
419                                 lo->ldo_sctrls = NULL;
420                                 return LDAP_OPT_SUCCESS;
421                         }
422                                 
423                         lo->ldo_sctrls = ldap_controls_dup( controls );
424
425                         if(lo->ldo_sctrls == NULL) {
426                                 /* memory allocation error ? */
427                                 break;
428                         }
429                 } return LDAP_OPT_SUCCESS;
430
431         case LDAP_OPT_CLIENT_CONTROLS: {
432                         LDAPControl *const *controls =
433                                 (LDAPControl *const *) invalue;
434
435                         if( lo->ldo_cctrls )
436                                 ldap_controls_free( lo->ldo_cctrls );
437
438                         if( controls == NULL || *controls == NULL ) {
439                                 lo->ldo_cctrls = NULL;
440                                 return LDAP_OPT_SUCCESS;
441                         }
442                                 
443                         lo->ldo_cctrls = ldap_controls_dup( controls );
444
445                         if(lo->ldo_cctrls == NULL) {
446                                 /* memory allocation error ? */
447                                 break;
448                         }
449                 } return LDAP_OPT_SUCCESS;
450
451         case LDAP_OPT_TIMEOUT: {
452                         const struct timeval *tv = 
453                                 (const struct timeval *) invalue;
454
455                         if ( lo->ldo_tm_api != NULL ) {
456                                 LDAP_FREE( lo->ldo_tm_api );
457                                 lo->ldo_tm_api = NULL;
458                         }
459
460                         if ( ldap_int_timeval_dup( &lo->ldo_tm_api, tv ) != 0 ) {
461                                 return LDAP_OPT_ERROR;
462                         }
463                 } return LDAP_OPT_SUCCESS;
464
465         case LDAP_OPT_NETWORK_TIMEOUT: {
466                         const struct timeval *tv = 
467                                 (const struct timeval *) invalue;
468
469                         if ( lo->ldo_tm_net != NULL ) {
470                                 LDAP_FREE( lo->ldo_tm_net );
471                                 lo->ldo_tm_net = NULL;
472                         }
473
474                         if ( ldap_int_timeval_dup( &lo->ldo_tm_net, tv ) != 0 ) {
475                                 return LDAP_OPT_ERROR;
476                         }
477                 } return LDAP_OPT_SUCCESS;
478
479         case LDAP_OPT_HOST_NAME: {
480                         const char *host = (const char *) invalue;
481                         LDAPURLDesc *ludlist = NULL;
482                         int rc = LDAP_OPT_SUCCESS;
483
484                         if(host != NULL) {
485                                 rc = ldap_url_parsehosts( &ludlist, host,
486                                         lo->ldo_defport ? lo->ldo_defport : LDAP_PORT );
487
488                         } else if(ld == NULL) {
489                                 /*
490                                  * must want global default returned
491                                  * to initial condition.
492                                  */
493                                 rc = ldap_url_parselist_ext(&ludlist, "ldap://localhost/", NULL,
494                                         LDAP_PVT_URL_PARSE_NOEMPTY_HOST
495                                         | LDAP_PVT_URL_PARSE_DEF_PORT );
496
497                         } else {
498                                 /*
499                                  * must want the session default
500                                  *   updated to the current global default
501                                  */
502                                 ludlist = ldap_url_duplist(
503                                         ldap_int_global_options.ldo_defludp);
504                                 if (ludlist == NULL)
505                                         rc = LDAP_NO_MEMORY;
506                         }
507
508                         if (rc == LDAP_OPT_SUCCESS) {
509                                 if (lo->ldo_defludp != NULL)
510                                         ldap_free_urllist(lo->ldo_defludp);
511                                 lo->ldo_defludp = ludlist;
512                         }
513                         return rc;
514                 }
515
516         case LDAP_OPT_URI: {
517                         const char *urls = (const char *) invalue;
518                         LDAPURLDesc *ludlist = NULL;
519                         int rc = LDAP_OPT_SUCCESS;
520
521                         if(urls != NULL) {
522                                 rc = ldap_url_parselist_ext(&ludlist, urls, NULL,
523                                         LDAP_PVT_URL_PARSE_NOEMPTY_HOST
524                                         | LDAP_PVT_URL_PARSE_DEF_PORT );
525                         } else if(ld == NULL) {
526                                 /*
527                                  * must want global default returned
528                                  * to initial condition.
529                                  */
530                                 rc = ldap_url_parselist_ext(&ludlist, "ldap://localhost/", NULL,
531                                         LDAP_PVT_URL_PARSE_NOEMPTY_HOST
532                                         | LDAP_PVT_URL_PARSE_DEF_PORT );
533
534                         } else {
535                                 /*
536                                  * must want the session default
537                                  *   updated to the current global default
538                                  */
539                                 ludlist = ldap_url_duplist(
540                                         ldap_int_global_options.ldo_defludp);
541                                 if (ludlist == NULL)
542                                         rc = LDAP_URL_ERR_MEM;
543                         }
544
545                         switch (rc) {
546                         case LDAP_URL_SUCCESS:          /* Success */
547                                 rc = LDAP_SUCCESS;
548                                 break;
549
550                         case LDAP_URL_ERR_MEM:          /* can't allocate memory space */
551                                 rc = LDAP_NO_MEMORY;
552                                 break;
553
554                         case LDAP_URL_ERR_PARAM:        /* parameter is bad */
555                         case LDAP_URL_ERR_BADSCHEME:    /* URL doesn't begin with "ldap[si]://" */
556                         case LDAP_URL_ERR_BADENCLOSURE: /* URL is missing trailing ">" */
557                         case LDAP_URL_ERR_BADURL:       /* URL is bad */
558                         case LDAP_URL_ERR_BADHOST:      /* host port is bad */
559                         case LDAP_URL_ERR_BADATTRS:     /* bad (or missing) attributes */
560                         case LDAP_URL_ERR_BADSCOPE:     /* scope string is invalid (or missing) */
561                         case LDAP_URL_ERR_BADFILTER:    /* bad or missing filter */
562                         case LDAP_URL_ERR_BADEXTS:      /* bad or missing extensions */
563                                 rc = LDAP_PARAM_ERROR;
564                                 break;
565                         }
566
567                         if (rc == LDAP_SUCCESS) {
568                                 if (lo->ldo_defludp != NULL)
569                                         ldap_free_urllist(lo->ldo_defludp);
570                                 lo->ldo_defludp = ludlist;
571                         }
572                         return rc;
573                 }
574
575         case LDAP_OPT_DEFBASE: {
576                         const char *newbase = (const char *) invalue;
577                         char *defbase = NULL;
578
579                         if ( newbase != NULL ) {
580                                 defbase = LDAP_STRDUP( newbase );
581                                 if ( defbase == NULL ) return LDAP_NO_MEMORY;
582
583                         } else if ( ld != NULL ) {
584                                 defbase = LDAP_STRDUP( ldap_int_global_options.ldo_defbase );
585                                 if ( defbase == NULL ) return LDAP_NO_MEMORY;
586                         }
587                         
588                         if ( lo->ldo_defbase != NULL )
589                                 LDAP_FREE( lo->ldo_defbase );
590                         lo->ldo_defbase = defbase;
591                 } return LDAP_OPT_SUCCESS;
592
593         case LDAP_OPT_DIAGNOSTIC_MESSAGE: {
594                         const char *err = (const char *) invalue;
595
596                         if(ld == NULL) {
597                                 /* need a struct ldap */
598                                 return LDAP_OPT_ERROR;
599                         }
600
601                         if( ld->ld_error ) {
602                                 LDAP_FREE(ld->ld_error);
603                                 ld->ld_error = NULL;
604                         }
605
606                         if ( err ) {
607                                 ld->ld_error = LDAP_STRDUP(err);
608                         }
609                 } return LDAP_OPT_SUCCESS;
610
611         case LDAP_OPT_MATCHED_DN: {
612                         const char *matched = (const char *) invalue;
613
614                         if (ld == NULL) {
615                                 /* need a struct ldap */
616                                 return LDAP_OPT_ERROR;
617                         }
618
619                         if( ld->ld_matched ) {
620                                 LDAP_FREE(ld->ld_matched);
621                                 ld->ld_matched = NULL;
622                         }
623
624                         if ( matched ) {
625                                 ld->ld_matched = LDAP_STRDUP( matched );
626                         }
627                 } return LDAP_OPT_SUCCESS;
628
629         case LDAP_OPT_REFERRAL_URLS: {
630                         char *const *referrals = (char *const *) invalue;
631                         
632                         if(ld == NULL) {
633                                 /* need a struct ldap */
634                                 return LDAP_OPT_ERROR;
635                         }
636
637                         if( ld->ld_referrals ) {
638                                 LDAP_VFREE(ld->ld_referrals);
639                         }
640
641                         if ( referrals ) {
642                                 ld->ld_referrals = ldap_value_dup(referrals);
643                         }
644                 } return LDAP_OPT_SUCCESS;
645
646         /* Only accessed from inside this function by ldap_set_rebind_proc() */
647         case LDAP_OPT_REBIND_PROC: {
648                         lo->ldo_rebind_proc = (LDAP_REBIND_PROC *)invalue;              
649                 } return LDAP_OPT_SUCCESS;
650         case LDAP_OPT_REBIND_PARAMS: {
651                         lo->ldo_rebind_params = (void *)invalue;                
652                 } return LDAP_OPT_SUCCESS;
653
654         /* Only accessed from inside this function by ldap_set_nextref_proc() */
655         case LDAP_OPT_NEXTREF_PROC: {
656                         lo->ldo_nextref_proc = (LDAP_NEXTREF_PROC *)invalue;            
657                 } return LDAP_OPT_SUCCESS;
658         case LDAP_OPT_NEXTREF_PARAMS: {
659                         lo->ldo_nextref_params = (void *)invalue;               
660                 } return LDAP_OPT_SUCCESS;
661
662         /* Only accessed from inside this function by ldap_set_urllist_proc() */
663         case LDAP_OPT_URLLIST_PROC: {
664                         lo->ldo_urllist_proc = (LDAP_URLLIST_PROC *)invalue;            
665                 } return LDAP_OPT_SUCCESS;
666         case LDAP_OPT_URLLIST_PARAMS: {
667                         lo->ldo_urllist_params = (void *)invalue;               
668                 } return LDAP_OPT_SUCCESS;
669
670         /* read-only options */
671         case LDAP_OPT_API_INFO:
672         case LDAP_OPT_DESC:
673         case LDAP_OPT_SOCKBUF:
674         case LDAP_OPT_API_FEATURE_INFO:
675                 return LDAP_OPT_ERROR;
676
677         /* options which cannot withstand invalue == NULL */
678         case LDAP_OPT_DEREF:
679         case LDAP_OPT_SIZELIMIT:
680         case LDAP_OPT_TIMELIMIT:
681         case LDAP_OPT_PROTOCOL_VERSION:
682         case LDAP_OPT_RESULT_CODE:
683         case LDAP_OPT_DEBUG_LEVEL:
684                 if(invalue == NULL) {
685                         /* no place to set from */
686                         return LDAP_OPT_ERROR;
687                 }
688                 break;
689
690         default:
691 #ifdef HAVE_TLS
692                 if ( ldap_pvt_tls_set_option( ld, option, (void *)invalue ) == 0 )
693                         return LDAP_OPT_SUCCESS;
694 #endif
695 #ifdef HAVE_CYRUS_SASL
696                 if ( ldap_int_sasl_set_option( ld, option, (void *)invalue ) == 0 )
697                         return LDAP_OPT_SUCCESS;
698 #endif
699                 /* bad param */
700                 return LDAP_OPT_ERROR;
701         }
702
703         /* options which cannot withstand invalue == NULL */
704
705         switch(option) {
706         case LDAP_OPT_DEREF:
707                 /* FIXME: check value for protocol compliance? */
708                 lo->ldo_deref = * (const int *) invalue;
709                 return LDAP_OPT_SUCCESS;
710
711         case LDAP_OPT_SIZELIMIT:
712                 /* FIXME: check value for protocol compliance? */
713                 lo->ldo_sizelimit = * (const int *) invalue;
714                 return LDAP_OPT_SUCCESS;
715
716         case LDAP_OPT_TIMELIMIT:
717                 /* FIXME: check value for protocol compliance? */
718                 lo->ldo_timelimit = * (const int *) invalue;
719                 return LDAP_OPT_SUCCESS;
720
721         case LDAP_OPT_PROTOCOL_VERSION: {
722                         int vers = * (const int *) invalue;
723                         if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) {
724                                 /* not supported */
725                                 break;
726                         }
727                         lo->ldo_version = vers;
728                 } return LDAP_OPT_SUCCESS;
729
730         case LDAP_OPT_RESULT_CODE: {
731                         int err = * (const int *) invalue;
732
733                         if(ld == NULL) {
734                                 /* need a struct ldap */
735                                 break;
736                         }
737
738                         ld->ld_errno = err;
739                 } return LDAP_OPT_SUCCESS;
740
741         case LDAP_OPT_DEBUG_LEVEL:
742                 lo->ldo_debug = * (const int *) invalue;
743                 return LDAP_OPT_SUCCESS;
744         }
745         return LDAP_OPT_ERROR;
746 }
747
748 int
749 ldap_set_rebind_proc( LDAP *ld, LDAP_REBIND_PROC *proc, void *params )
750 {
751         int rc;
752         rc = ldap_set_option( ld, LDAP_OPT_REBIND_PROC, (void *)proc );
753         if( rc != LDAP_OPT_SUCCESS ) return rc;
754
755         rc = ldap_set_option( ld, LDAP_OPT_REBIND_PARAMS, (void *)params );
756         return rc;
757 }
758
759 int
760 ldap_set_nextref_proc( LDAP *ld, LDAP_NEXTREF_PROC *proc, void *params )
761 {
762         int rc;
763         rc = ldap_set_option( ld, LDAP_OPT_NEXTREF_PROC, (void *)proc );
764         if( rc != LDAP_OPT_SUCCESS ) return rc;
765
766         rc = ldap_set_option( ld, LDAP_OPT_NEXTREF_PARAMS, (void *)params );
767         return rc;
768 }
769
770 int
771 ldap_set_urllist_proc( LDAP *ld, LDAP_URLLIST_PROC *proc, void *params )
772 {
773         int rc;
774         rc = ldap_set_option( ld, LDAP_OPT_URLLIST_PROC, (void *)proc );
775         if( rc != LDAP_OPT_SUCCESS ) return rc;
776
777         rc = ldap_set_option( ld, LDAP_OPT_URLLIST_PARAMS, (void *)params );
778         return rc;
779 }