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