1/* $OpenLDAP$ */
2/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3 *
4 * Copyright 1998-2011 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 <ac/stdlib.h>
19#include <ac/string.h>
20#include <ac/stdarg.h>
21#include "lber-int.h"
22
23char ber_pvt_opt_on;	/* used to get a non-NULL address for *_OPT_ON */
24
25struct lber_options ber_int_options = {
26	LBER_UNINITIALIZED, 0, 0 };
27
28static BerMemoryFunctions	ber_int_memory_fns_datum;
29
30int
31ber_get_option(
32	void	*item,
33	int		option,
34	void	*outvalue)
35{
36	const BerElement *ber;
37	const Sockbuf *sb;
38
39	if(outvalue == NULL) {
40		/* no place to get to */
41		ber_errno = LBER_ERROR_PARAM;
42		return LBER_OPT_ERROR;
43	}
44
45	if(item == NULL) {
46		switch ( option ) {
47		case LBER_OPT_BER_DEBUG:
48			* (int *) outvalue = ber_int_debug;
49			return LBER_OPT_SUCCESS;
50
51		case LBER_OPT_MEMORY_INUSE:
52			/* The memory inuse is a global variable on kernal implementations.
53			 * This means that memory debug is shared by all LDAP processes
54			 * so for this variable to have much meaning, only one LDAP process
55			 * should be running and memory inuse should be initialized to zero
56			 * using the lber_set_option() function during startup.
57			 * The counter is not accurate for multithreaded ldap applications.
58			 */
59#ifdef LDAP_MEMORY_DEBUG
60			* (int *) outvalue = ber_int_meminuse;
61			return LBER_OPT_SUCCESS;
62#else
63			return LBER_OPT_ERROR;
64#endif
65
66		case LBER_OPT_LOG_PRINT_FILE:
67			*((FILE**)outvalue) = (FILE*)ber_pvt_err_file;
68			return LBER_OPT_SUCCESS;
69		}
70
71		ber_errno = LBER_ERROR_PARAM;
72		return LBER_OPT_ERROR;
73	}
74
75	ber = item;
76	sb = item;
77
78	switch(option) {
79	case LBER_OPT_BER_OPTIONS:
80		assert( LBER_VALID( ber ) );
81		* (int *) outvalue = ber->ber_options;
82		return LBER_OPT_SUCCESS;
83
84	case LBER_OPT_BER_DEBUG:
85		assert( LBER_VALID( ber ) );
86		* (int *) outvalue = ber->ber_debug;
87		return LBER_OPT_SUCCESS;
88
89	case LBER_OPT_BER_REMAINING_BYTES:
90		assert( LBER_VALID( ber ) );
91		*((ber_len_t *) outvalue) = ber_pvt_ber_remaining(ber);
92		return LBER_OPT_SUCCESS;
93
94	case LBER_OPT_BER_TOTAL_BYTES:
95		assert( LBER_VALID( ber ) );
96		*((ber_len_t *) outvalue) = ber_pvt_ber_total(ber);
97		return LBER_OPT_SUCCESS;
98
99	case LBER_OPT_BER_BYTES_TO_WRITE:
100		assert( LBER_VALID( ber ) );
101		*((ber_len_t *) outvalue) = ber_pvt_ber_write(ber);
102		return LBER_OPT_SUCCESS;
103
104	case LBER_OPT_BER_MEMCTX:
105		assert( LBER_VALID( ber ) );
106		*((void **) outvalue) = ber->ber_memctx;
107		return LBER_OPT_SUCCESS;
108
109	default:
110		/* bad param */
111		ber_errno = LBER_ERROR_PARAM;
112		break;
113	}
114
115	return LBER_OPT_ERROR;
116}
117
118int
119ber_set_option(
120	void	*item,
121	int		option,
122	LDAP_CONST void	*invalue)
123{
124	BerElement *ber;
125	Sockbuf *sb;
126
127	if(invalue == NULL) {
128		/* no place to set from */
129		ber_errno = LBER_ERROR_PARAM;
130		return LBER_OPT_ERROR;
131	}
132
133	if(item == NULL) {
134		switch ( option ) {
135		case LBER_OPT_BER_DEBUG:
136			ber_int_debug = * (const int *) invalue;
137			return LBER_OPT_SUCCESS;
138
139		case LBER_OPT_LOG_PRINT_FN:
140			ber_pvt_log_print = (BER_LOG_PRINT_FN) invalue;
141			return LBER_OPT_SUCCESS;
142
143		case LBER_OPT_LOG_PRINT_FILE:
144			ber_pvt_err_file = (void *) invalue;
145			return LBER_OPT_SUCCESS;
146
147		case LBER_OPT_MEMORY_INUSE:
148			/* The memory inuse is a global variable on kernal implementations.
149			 * This means that memory debug is shared by all LDAP processes
150			 * so for this variable to have much meaning, only one LDAP process
151			 * should be running and memory inuse should be initialized to zero
152			 * using the lber_set_option() function during startup.
153			 * The counter is not accurate for multithreaded applications.
154			 */
155#ifdef LDAP_MEMORY_DEBUG
156			ber_int_meminuse = * (int *) invalue;
157			return LBER_OPT_SUCCESS;
158#else
159			return LBER_OPT_ERROR;
160#endif
161		case LBER_OPT_MEMORY_FNS:
162			if ( ber_int_memory_fns == NULL )
163			{
164				const BerMemoryFunctions *f =
165					(const BerMemoryFunctions *) invalue;
166				/* make sure all functions are provided */
167				if(!( f->bmf_malloc && f->bmf_calloc
168					&& f->bmf_realloc && f->bmf_free ))
169				{
170					ber_errno = LBER_ERROR_PARAM;
171					return LBER_OPT_ERROR;
172				}
173
174				ber_int_memory_fns = &ber_int_memory_fns_datum;
175
176				AC_MEMCPY(ber_int_memory_fns, f,
177					 sizeof(BerMemoryFunctions));
178
179				return LBER_OPT_SUCCESS;
180			}
181			break;
182
183		case LBER_OPT_LOG_PROC:
184			ber_int_log_proc = (BER_LOG_FN)invalue;
185			return LBER_OPT_SUCCESS;
186		}
187
188		ber_errno = LBER_ERROR_PARAM;
189		return LBER_OPT_ERROR;
190	}
191
192	ber = item;
193	sb = item;
194
195	switch(option) {
196	case LBER_OPT_BER_OPTIONS:
197		assert( LBER_VALID( ber ) );
198		ber->ber_options = * (const int *) invalue;
199		return LBER_OPT_SUCCESS;
200
201	case LBER_OPT_BER_DEBUG:
202		assert( LBER_VALID( ber ) );
203		ber->ber_debug = * (const int *) invalue;
204		return LBER_OPT_SUCCESS;
205
206	case LBER_OPT_BER_REMAINING_BYTES:
207		assert( LBER_VALID( ber ) );
208		ber->ber_end = &ber->ber_ptr[* (const ber_len_t *) invalue];
209		return LBER_OPT_SUCCESS;
210
211	case LBER_OPT_BER_TOTAL_BYTES:
212		assert( LBER_VALID( ber ) );
213		ber->ber_end = &ber->ber_buf[* (const ber_len_t *) invalue];
214		return LBER_OPT_SUCCESS;
215
216	case LBER_OPT_BER_BYTES_TO_WRITE:
217		assert( LBER_VALID( ber ) );
218		ber->ber_ptr = &ber->ber_buf[* (const ber_len_t *) invalue];
219		return LBER_OPT_SUCCESS;
220
221	case LBER_OPT_BER_MEMCTX:
222		assert( LBER_VALID( ber ) );
223		ber->ber_memctx = *(void **)invalue;
224		return LBER_OPT_SUCCESS;
225
226	default:
227		/* bad param */
228		ber_errno = LBER_ERROR_PARAM;
229		break;
230	}
231
232	return LBER_OPT_ERROR;
233}
234