1/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
2 *
3 * Copyright 1999-2011 The OpenLDAP Foundation.
4 * Portions Copyright 1999 Dmitry Kovalev.
5 * Portions Copyright 2004 Pierangelo Masarati.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
10 * Public License.
11 *
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
15 */
16/* ACKNOWLEDGEMENTS:
17 * This work was initially developed by Dmitry Kovalev for inclusion
18 * by OpenLDAP Software.  Additional significant contributors include
19 * Pierangelo Masarati.
20 */
21
22#include "portable.h"
23
24#include <stdio.h>
25#include <sys/types.h>
26#include "ac/string.h"
27
28#include "slap.h"
29#include "proto-sql.h"
30
31static backsql_api *backsqlapi;
32
33int
34backsql_api_config( backsql_info *bi, const char *name, int argc, char *argv[] )
35{
36	backsql_api	*ba;
37
38	assert( bi != NULL );
39	assert( name != NULL );
40
41	for ( ba = backsqlapi; ba; ba = ba->ba_next ) {
42		if ( strcasecmp( name, ba->ba_name ) == 0 ) {
43			backsql_api	*ba2;
44
45			ba2 = ch_malloc( sizeof( backsql_api ) );
46			*ba2 = *ba;
47
48			if ( ba2->ba_config ) {
49				if ( ( *ba2->ba_config )( ba2, argc, argv ) ) {
50					ch_free( ba2 );
51					return 1;
52				}
53				ba2->ba_argc = argc;
54				if ( argc ) {
55					int i;
56					ba2->ba_argv = ch_malloc( argc * sizeof(char *));
57					for ( i=0; i<argc; i++ )
58						ba2->ba_argv[i] = ch_strdup( argv[i] );
59				}
60			}
61
62			ba2->ba_next = bi->sql_api;
63			bi->sql_api = ba2;
64			return 0;
65		}
66	}
67
68	return 1;
69}
70
71int
72backsql_api_destroy( backsql_info *bi )
73{
74	backsql_api	*ba;
75
76	assert( bi != NULL );
77
78	ba = bi->sql_api;
79
80	if ( ba == NULL ) {
81		return 0;
82	}
83
84	for ( ; ba; ba = ba->ba_next ) {
85		if ( ba->ba_destroy ) {
86			(void)( *ba->ba_destroy )( ba );
87		}
88	}
89
90	return 0;
91}
92
93int
94backsql_api_register( backsql_api *ba )
95{
96	backsql_api	*ba2;
97
98	assert( ba != NULL );
99	assert( ba->ba_private == NULL );
100
101	if ( ba->ba_name == NULL ) {
102		fprintf( stderr, "API module has no name\n" );
103		exit(EXIT_FAILURE);
104	}
105
106	for ( ba2 = backsqlapi; ba2; ba2 = ba2->ba_next ) {
107		if ( strcasecmp( ba->ba_name, ba2->ba_name ) == 0 ) {
108			fprintf( stderr, "API module \"%s\" already defined\n", ba->ba_name );
109			exit( EXIT_FAILURE );
110		}
111	}
112
113	ba->ba_next = backsqlapi;
114	backsqlapi = ba;
115
116	return 0;
117}
118
119int
120backsql_api_dn2odbc( Operation *op, SlapReply *rs, struct berval *dn )
121{
122	backsql_info	*bi = (backsql_info *)op->o_bd->be_private;
123	backsql_api	*ba;
124	int		rc;
125	struct berval	bv;
126
127	ba = bi->sql_api;
128
129	if ( ba == NULL ) {
130		return 0;
131	}
132
133	ber_dupbv( &bv, dn );
134
135	for ( ; ba; ba = ba->ba_next ) {
136		if ( ba->ba_dn2odbc ) {
137			/*
138			 * The dn2odbc() helper is supposed to rewrite
139			 * the contents of bv, freeing the original value
140			 * with ch_free() if required and replacing it
141			 * with a newly allocated one using ch_malloc()
142			 * or companion functions.
143			 *
144			 * NOTE: it is supposed to __always__ free
145			 * the value of bv in case of error, and reset
146			 * it with BER_BVZERO() .
147			 */
148			rc = ( *ba->ba_dn2odbc )( op, rs, &bv );
149
150			if ( rc ) {
151				/* in case of error, dn2odbc() must cleanup */
152				assert( BER_BVISNULL( &bv ) );
153
154				return rc;
155			}
156		}
157	}
158
159	assert( !BER_BVISNULL( &bv ) );
160
161	*dn = bv;
162
163	return 0;
164}
165
166int
167backsql_api_odbc2dn( Operation *op, SlapReply *rs, struct berval *dn )
168{
169	backsql_info	*bi = (backsql_info *)op->o_bd->be_private;
170	backsql_api	*ba;
171	int		rc;
172	struct berval	bv;
173
174	ba = bi->sql_api;
175
176	if ( ba == NULL ) {
177		return 0;
178	}
179
180	ber_dupbv( &bv, dn );
181
182	for ( ; ba; ba = ba->ba_next ) {
183		if ( ba->ba_dn2odbc ) {
184			rc = ( *ba->ba_odbc2dn )( op, rs, &bv );
185			/*
186			 * The odbc2dn() helper is supposed to rewrite
187			 * the contents of bv, freeing the original value
188			 * with ch_free() if required and replacing it
189			 * with a newly allocated one using ch_malloc()
190			 * or companion functions.
191			 *
192			 * NOTE: it is supposed to __always__ free
193			 * the value of bv in case of error, and reset
194			 * it with BER_BVZERO() .
195			 */
196			if ( rc ) {
197				/* in case of error, odbc2dn() must cleanup */
198				assert( BER_BVISNULL( &bv ) );
199
200				return rc;
201			}
202		}
203	}
204
205	assert( !BER_BVISNULL( &bv ) );
206
207	*dn = bv;
208
209	return 0;
210}
211
212