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