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