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