]> git.sur5r.net Git - openldap/blob - libraries/libldap/options.c
Minor adjustments based upon initial read of draft-ietf-ldapext-ldap-c-api-04.txt.
[openldap] / libraries / libldap / options.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6
7 #include "portable.h"
8
9 #include <stdio.h>
10
11 #include <ac/stdlib.h>
12
13 #include <ac/socket.h>
14 #include <ac/string.h>
15 #include <ac/time.h>
16
17 #include "ldap-int.h"
18
19 static const LDAPAPIFeatureInfo features[] = {
20 #ifdef LDAP_API_FEATURE_X_OPENLDAP
21         {       /* OpenLDAP Extensions API Feature */
22                 LDAP_FEATURE_INFO_VERSION,
23                 "X_OPENLDAP",
24                 LDAP_API_FEATURE_X_OPENLDAP
25         },
26 #endif
27
28 #ifdef LDAP_API_FEATURE_THREAD_SAFE
29         {       /* Basic Thread Safe */
30                 LDAP_FEATURE_INFO_VERSION,
31                 "THREAD_SAFE",
32                 LDAP_API_FEATURE_THREAD_SAFE
33         },
34 #endif
35 #ifdef LDAP_API_FEATURE_SESSION_THREAD_SAFE
36         {       /* Session Thread Safe */
37                 LDAP_FEATURE_INFO_VERSION,
38                 "SESSION_THREAD_SAFE",
39                 LDAP_API_FEATURE_SESSION_THREAD_SAFE
40         },
41 #endif
42 #ifdef LDAP_API_FEATURE_OPERATION_THREAD_SAFE
43         {       /* Operation Thread Safe */
44                 LDAP_FEATURE_INFO_VERSION,
45                 "OPERATION_THREAD_SAFE",
46                 LDAP_API_FEATURE_OPERATION_THREAD_SAFE
47         },
48 #endif
49 #ifdef LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
50         {       /* OpenLDAP Reentrant */
51                 LDAP_FEATURE_INFO_VERSION,
52                 "X_OPENLDAP_REENTRANT",
53                 LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
54         },
55 #endif
56 #if defined( LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE ) && \
57         defined( LDAP_THREAD_SAFE )
58         {       /* OpenLDAP Thread Safe */
59                 LDAP_FEATURE_INFO_VERSION,
60                 "X_OPENLDAP_THREAD_SAFE",
61                 LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE
62         },
63 #endif
64 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS
65         {       /* DNS */
66                 LDAP_FEATURE_INFO_VERSION,
67                 "X_OPENLDAP_V2_DNS",
68                 LDAP_API_FEATURE_X_OPENLDAP_V2_DNS
69         },
70 #endif
71 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
72         {       /* V2 Referrals */
73                 LDAP_FEATURE_INFO_VERSION,
74                 "X_OPENLDAP_V2_REFERRALS",
75                 LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
76         },
77 #endif
78         {0, NULL, 0}
79 };
80
81 int
82 ldap_get_option(
83         LDAP    *ld,
84         int             option,
85         void    *outvalue)
86 {
87         const struct ldapoptions *lo;
88
89         if( ldap_int_global_options.ldo_valid != LDAP_INITIALIZED ) {
90                 ldap_int_initialize();
91         }
92
93         if(ld == NULL) {
94                 lo = &ldap_int_global_options;
95
96         } else {
97                 assert( LDAP_VALID( ld ) );
98
99                 if( !LDAP_VALID( ld ) ) {
100                         return LDAP_OPT_ERROR;
101                 }
102
103                 lo = &ld->ld_options;
104         }
105
106         if(outvalue == NULL) {
107                 /* no place to get to */
108                 return LDAP_OPT_ERROR;
109         }
110
111         switch(option) {
112         case LDAP_OPT_API_INFO: {
113                         struct ldapapiinfo *info = (struct ldapapiinfo *) outvalue;
114
115                         if(info == NULL) {
116                                 /* outvalue must point to an apiinfo structure */
117                                 return LDAP_OPT_ERROR;
118                         }
119
120                         if(info->ldapai_info_version != LDAP_API_INFO_VERSION) {
121                                 /* api info version mismatch */
122                                 info->ldapai_info_version = LDAP_API_INFO_VERSION;
123                                 return LDAP_OPT_ERROR;
124                         }
125
126                         info->ldapai_api_version = LDAP_API_VERSION;
127                         info->ldapai_api_version = LDAP_API_VERSION;
128                         info->ldapai_protocol_version = LDAP_VERSION_MAX;
129
130                         if(features[0].ldapaif_name == NULL) {
131                                 info->ldapai_extensions = NULL;
132                         } else {
133                                 int i;
134                                 info->ldapai_extensions = LDAP_MALLOC(sizeof(char *) *
135                                         sizeof(features)/sizeof(LDAPAPIFeatureInfo));
136
137                                 for(i=0; features[i].ldapaif_name != NULL; i++) {
138                                         info->ldapai_extensions[i] =
139                                                 LDAP_STRDUP(features[i].ldapaif_name);
140                                 }
141
142                                 info->ldapai_extensions[i] = NULL;
143                         }
144
145                         info->ldapai_vendor_name = LDAP_STRDUP(LDAP_VENDOR_NAME);
146                         info->ldapai_vendor_version = LDAP_VENDOR_VERSION;
147
148                         return LDAP_OPT_SUCCESS;
149                 } break;
150
151         case LDAP_OPT_DESC:
152                 if(ld == NULL) {
153                         /* bad param */
154                         break;
155                 } 
156
157                 * (ber_socket_t *) outvalue = ber_pvt_sb_get_desc( &(ld->ld_sb) );
158                 return LDAP_OPT_SUCCESS;
159
160         case LDAP_OPT_TIMEOUT:
161                 /* the caller has to free outvalue ! */
162                 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_api) != 0 )
163                 {
164                         return LDAP_OPT_ERROR;
165                 }
166                 return LDAP_OPT_SUCCESS;
167                 
168         case LDAP_OPT_NETWORK_TIMEOUT:
169                 /* the caller has to free outvalue ! */
170                 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_net ) != 0 )
171                 {
172                         return LDAP_OPT_ERROR;
173                 }
174                 return LDAP_OPT_SUCCESS;
175
176         case LDAP_OPT_DEREF:
177                 * (int *) outvalue = lo->ldo_deref;
178                 return LDAP_OPT_SUCCESS;
179
180         case LDAP_OPT_SIZELIMIT:
181                 * (int *) outvalue = lo->ldo_sizelimit;
182                 return LDAP_OPT_SUCCESS;
183
184         case LDAP_OPT_TIMELIMIT:
185                 * (int *) outvalue = lo->ldo_timelimit;
186                 return LDAP_OPT_SUCCESS;
187
188         case LDAP_OPT_REFERRALS:
189                 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_REFERRALS);
190                 return LDAP_OPT_SUCCESS;
191                 
192         case LDAP_OPT_RESTART:
193                 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_RESTART);
194                 return LDAP_OPT_SUCCESS;
195
196         case LDAP_OPT_DNS:      /* LDAPv2 */
197                 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_DNS);
198                 return LDAP_OPT_SUCCESS;
199
200         case LDAP_OPT_PROTOCOL_VERSION:
201                 if ((ld != NULL) && ld->ld_version) {
202                         * (int *) outvalue = ld->ld_version;
203                 } else { 
204                         * (int *) outvalue = lo->ldo_version;
205                 }
206                 return LDAP_OPT_SUCCESS;
207
208         case LDAP_OPT_SERVER_CONTROLS:
209                 * (LDAPControl ***) outvalue =
210                         ldap_controls_dup( lo->ldo_sctrls );
211
212                 return LDAP_OPT_SUCCESS;
213
214         case LDAP_OPT_CLIENT_CONTROLS:
215                 * (LDAPControl ***) outvalue =
216                         ldap_controls_dup( lo->ldo_cctrls );
217
218                 return LDAP_OPT_SUCCESS;
219
220         case LDAP_OPT_HOST_NAME:
221                 * (char **) outvalue = LDAP_STRDUP(lo->ldo_defhost);
222                 return LDAP_OPT_SUCCESS;
223
224         case LDAP_OPT_ERROR_NUMBER:
225                 if(ld == NULL) {
226                         /* bad param */
227                         break;
228                 } 
229                 * (int *) outvalue = ld->ld_errno;
230                 return LDAP_OPT_SUCCESS;
231
232         case LDAP_OPT_ERROR_STRING:
233                 if(ld == NULL) {
234                         /* bad param */
235                         break;
236                 } 
237
238                 if( ld->ld_error == NULL ) {
239                         * (char **) outvalue = NULL;
240                 } else {
241                         * (char **) outvalue = LDAP_STRDUP(ld->ld_error);
242                 }
243
244                 return LDAP_OPT_SUCCESS;
245
246         case LDAP_OPT_MATCHED_DN:
247                 if(ld == NULL) {
248                         /* bad param */
249                         break;
250                 } 
251
252                 if( ld->ld_matched == NULL ) {
253                         * (char **) outvalue = NULL;
254                 } else {
255                         * (char **) outvalue = LDAP_STRDUP(ld->ld_matched);
256                 }
257
258                 return LDAP_OPT_SUCCESS;
259
260         case LDAP_OPT_API_FEATURE_INFO: {
261                         LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue;
262                         int i;
263
264                         if(info == NULL) return LDAP_OPT_ERROR;
265
266                         if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) {
267                                 /* api info version mismatch */
268                                 info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
269                                 return LDAP_OPT_ERROR;
270                         }
271
272                         if(info->ldapaif_name == NULL) return LDAP_OPT_ERROR;
273
274                         for(i=0; features[i].ldapaif_name != NULL; i++) {
275                                 if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) {
276                                         info->ldapaif_version =
277                                                 features[i].ldapaif_version;
278                                         return LDAP_OPT_SUCCESS;
279                                 }
280                         }
281                 }
282                 break;
283
284         case LDAP_OPT_DEBUG_LEVEL:
285                 * (int *) outvalue = lo->ldo_debug;
286                 return LDAP_OPT_SUCCESS;
287
288         default:
289 #ifdef HAVE_TLS
290                 if ( ldap_pvt_tls_get_option(lo, option, outvalue ) == 0 )
291                         return LDAP_OPT_SUCCESS;
292 #endif
293                 /* bad param */
294                 break;
295         }
296
297         return LDAP_OPT_ERROR;
298 }
299
300 int
301 ldap_set_option(
302         LDAP    *ld,
303         int             option,
304         LDAP_CONST void *invalue)
305 {
306         struct ldapoptions *lo;
307
308         if( ldap_int_global_options.ldo_valid != LDAP_INITIALIZED ) {
309                 ldap_int_initialize();
310         }
311
312         if(ld == NULL) {
313                 lo = &ldap_int_global_options;
314
315         } else {
316                 assert( LDAP_VALID( ld ) );
317
318                 if( !LDAP_VALID( ld ) ) {
319                         return LDAP_OPT_ERROR;
320                 }
321
322                 lo = &ld->ld_options;
323         }
324
325         switch(option) {
326         case LDAP_OPT_REFERRALS:
327                 if(invalue == LDAP_OPT_OFF) {
328                         LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS);
329                 } else {
330                         LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS);
331                 }
332                 return LDAP_OPT_SUCCESS;
333
334         case LDAP_OPT_RESTART:
335                 if(invalue == LDAP_OPT_OFF) {
336                         LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART);
337                 } else {
338                         LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART);
339                 }
340                 return LDAP_OPT_SUCCESS;
341         }
342
343         /* options which can withstand invalue == NULL */
344         switch ( option ) {
345         case LDAP_OPT_SERVER_CONTROLS: {
346                         LDAPControl *const *controls =
347                                 (LDAPControl *const *) invalue;
348
349                         ldap_controls_free( lo->ldo_sctrls );
350
351                         if( controls == NULL || *controls == NULL ) {
352                                 lo->ldo_sctrls = NULL;
353                                 return LDAP_OPT_SUCCESS;
354                         }
355                                 
356                         lo->ldo_sctrls = ldap_controls_dup( controls );
357
358                         if(lo->ldo_sctrls == NULL) {
359                                 /* memory allocation error ? */
360                                 break;
361                         }
362                 } return LDAP_OPT_SUCCESS;
363
364         case LDAP_OPT_CLIENT_CONTROLS: {
365                         LDAPControl *const *controls =
366                                 (LDAPControl *const *) invalue;
367
368                         ldap_controls_free( lo->ldo_cctrls );
369
370                         if( controls == NULL || *controls == NULL ) {
371                                 lo->ldo_cctrls = NULL;
372                                 return LDAP_OPT_SUCCESS;
373                         }
374                                 
375                         lo->ldo_cctrls = ldap_controls_dup( controls );
376
377                         if(lo->ldo_cctrls == NULL) {
378                                 /* memory allocation error ? */
379                                 break;
380                         }
381                 } return LDAP_OPT_SUCCESS;
382
383         case LDAP_OPT_TIMEOUT: {
384                         const struct timeval *tv = 
385                                 (const struct timeval *) invalue;
386
387                         if ( lo->ldo_tm_api != NULL ) {
388                                 LDAP_FREE( lo->ldo_tm_api );
389                                 lo->ldo_tm_api = NULL;
390                         }
391
392                         if ( ldap_int_timeval_dup( &lo->ldo_tm_api, tv ) != 0 ) {
393                                 return LDAP_OPT_ERROR;
394                         }
395                 } return LDAP_OPT_SUCCESS;
396
397         case LDAP_OPT_NETWORK_TIMEOUT: {
398                         const struct timeval *tv = 
399                                 (const struct timeval *) invalue;
400
401                         if ( lo->ldo_tm_net != NULL ) {
402                                 LDAP_FREE( lo->ldo_tm_net );
403                                 lo->ldo_tm_net = NULL;
404                         }
405
406                         if ( ldap_int_timeval_dup( &lo->ldo_tm_net, tv ) != 0 ) {
407                                 return LDAP_OPT_ERROR;
408                         }
409                 } return LDAP_OPT_SUCCESS;
410         }
411
412         if(invalue == NULL) {
413                 /* no place to set from */
414                 return LDAP_OPT_ERROR;
415         }
416
417         /* options which cannot withstand invalue == NULL */
418
419         switch(option) {
420         case LDAP_OPT_API_INFO:
421         case LDAP_OPT_DESC:
422                 /* READ ONLY */
423                 break;
424
425         case LDAP_OPT_DEREF:
426                 lo->ldo_deref = * (const int *) invalue;
427                 return LDAP_OPT_SUCCESS;
428
429         case LDAP_OPT_SIZELIMIT:
430                 lo->ldo_sizelimit = * (const int *) invalue;
431                 return LDAP_OPT_SUCCESS;
432
433         case LDAP_OPT_TIMELIMIT:
434                 lo->ldo_timelimit = * (const int *) invalue;
435                 return LDAP_OPT_SUCCESS;
436
437         case LDAP_OPT_PROTOCOL_VERSION: {
438                         int vers = * (const int *) invalue;
439                         if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) {
440                                 /* not supported */
441                                 break;
442                         }
443                         ld->ld_version = vers;
444                 } return LDAP_OPT_SUCCESS;
445
446
447         case LDAP_OPT_HOST_NAME: {
448                         const char *host = (const char *) invalue;
449
450                         if(lo->ldo_defhost != NULL) {
451                                 LDAP_FREE(lo->ldo_defhost);
452                                 lo->ldo_defhost = NULL;
453                         }
454
455                         if(host != NULL) {
456                                 lo->ldo_defhost = LDAP_STRDUP(host);
457                                 return LDAP_OPT_SUCCESS;
458                         }
459
460                         if(ld == NULL) {
461                                 /*
462                                  * must want global default returned
463                                  * to initial condition.
464                                  */
465                                 lo->ldo_defhost = LDAP_STRDUP("localhost");
466
467                         } else {
468                                 /*
469                                  * must want the session default
470                                  *   updated to the current global default
471                                  */
472                                 lo->ldo_defhost = LDAP_STRDUP(
473                                         ldap_int_global_options.ldo_defhost);
474                         }
475                 } return LDAP_OPT_SUCCESS;
476
477         case LDAP_OPT_ERROR_NUMBER: {
478                         int err = * (const int *) invalue;
479
480                         if(ld == NULL) {
481                                 /* need a struct ldap */
482                                 break;
483                         }
484
485                         ld->ld_errno = err;
486                 } return LDAP_OPT_SUCCESS;
487
488         case LDAP_OPT_ERROR_STRING: {
489                         const char *err = (const char *) invalue;
490
491                         if(ld == NULL) {
492                                 /* need a struct ldap */
493                                 break;
494                         }
495
496                         if( ld->ld_error ) {
497                                 LDAP_FREE(ld->ld_error);
498                         }
499
500                         ld->ld_error = LDAP_STRDUP(err);
501                 } return LDAP_OPT_SUCCESS;
502
503         case LDAP_OPT_MATCHED_DN: {
504                         const char *err = (const char *) invalue;
505
506                         if(ld == NULL) {
507                                 /* need a struct ldap */
508                                 break;
509                         }
510
511                         if( ld->ld_matched ) {
512                                 LDAP_FREE(ld->ld_matched);
513                         }
514
515                         ld->ld_matched = LDAP_STRDUP(err);
516                 } return LDAP_OPT_SUCCESS;
517
518         case LDAP_OPT_API_FEATURE_INFO:
519                 /* read-only */
520                 break;
521
522         case LDAP_OPT_DEBUG_LEVEL:
523                 lo->ldo_debug = * (const int *) invalue;
524                 return LDAP_OPT_SUCCESS;
525
526         default:
527 #ifdef HAVE_TLS
528                 if ( ldap_pvt_tls_set_option( lo, option, invalue ) == 0 )
529                         return LDAP_OPT_SUCCESS;
530 #endif
531                 /* bad param */
532                 break;
533         }
534         return LDAP_OPT_ERROR;
535 }