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