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