1 /*	$NetBSD: init.c,v 1.1.1.3 2010/12/12 15:23:21 adam Exp $	*/
2 
3 /* init.c - initialize relay backend */
4 /* OpenLDAP: pkg/ldap/servers/slapd/back-relay/init.c,v 1.19.2.9 2010/04/13 20:23:38 kurt Exp */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 2004-2010 The OpenLDAP Foundation.
8  * Portions Copyright 2004 Pierangelo Masarati.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted only as authorized by the OpenLDAP
13  * Public License.
14  *
15  * A copy of this license is available in the file LICENSE in the
16  * top-level directory of the distribution or, alternatively, at
17  * <http://www.OpenLDAP.org/license.html>.
18  */
19 /* ACKNOWLEDGEMENTS:
20  * This work was initially developed by Pierangelo Masarati for inclusion
21  * in OpenLDAP Software.
22  */
23 
24 #include "portable.h"
25 
26 #include <stdio.h>
27 #include <ac/string.h>
28 
29 #include "slap.h"
30 #include "config.h"
31 #include "back-relay.h"
32 
33 static ConfigDriver relay_back_cf;
34 
35 static ConfigTable relaycfg[] = {
36 	{ "relay", "relay", 2, 2, 0,
37 		ARG_MAGIC|ARG_DN,
38 		relay_back_cf, "( OLcfgDbAt:5.1 "
39 			"NAME 'olcRelay' "
40 			"DESC 'Relay DN' "
41 			"SYNTAX OMsDN "
42 			"SINGLE-VALUE )",
43 		NULL, NULL },
44 	{ NULL }
45 };
46 
47 static ConfigOCs relayocs[] = {
48 	{ "( OLcfgDbOc:5.1 "
49 		"NAME 'olcRelayConfig' "
50 		"DESC 'Relay backend configuration' "
51 		"SUP olcDatabaseConfig "
52 		"MAY ( olcRelay "
53 		") )",
54 		 	Cft_Database, relaycfg},
55 	{ NULL, 0, NULL }
56 };
57 
58 static int
59 relay_back_cf( ConfigArgs *c )
60 {
61 	relay_back_info	*ri = ( relay_back_info * )c->be->be_private;
62 	int		rc = 0;
63 
64 	if ( c->op == SLAP_CONFIG_EMIT ) {
65 		if ( ri != NULL && !BER_BVISNULL( &ri->ri_realsuffix ) ) {
66 			value_add_one( &c->rvalue_vals, &ri->ri_realsuffix );
67 			return 0;
68 		}
69 		return 1;
70 
71 	} else if ( c->op == LDAP_MOD_DELETE ) {
72 		if ( !BER_BVISNULL( &ri->ri_realsuffix ) ) {
73 			ch_free( ri->ri_realsuffix.bv_val );
74 			BER_BVZERO( &ri->ri_realsuffix );
75 			ri->ri_bd = NULL;
76 			return 0;
77 		}
78 		return 1;
79 
80 	} else {
81 		BackendDB *bd;
82 
83 		assert( ri != NULL );
84 		assert( BER_BVISNULL( &ri->ri_realsuffix ) );
85 
86 		if ( c->be->be_nsuffix == NULL ) {
87 			snprintf( c->cr_msg, sizeof( c->cr_msg),
88 				"\"relay\" directive "
89 				"must appear after \"suffix\"" );
90 			Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
91 				"%s: %s.\n", c->log, c->cr_msg );
92 			rc = 1;
93 			goto relay_done;
94 		}
95 
96 		if ( !BER_BVISNULL( &c->be->be_nsuffix[ 1 ] ) ) {
97 			snprintf( c->cr_msg, sizeof( c->cr_msg),
98 				"relaying of multiple suffix "
99 				"database not supported" );
100 			Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
101 				"%s: %s.\n", c->log, c->cr_msg );
102 			rc = 1;
103 			goto relay_done;
104 		}
105 
106 		bd = select_backend( &c->value_ndn, 1 );
107 		if ( bd == NULL ) {
108 			snprintf( c->cr_msg, sizeof( c->cr_msg),
109 				"cannot find database "
110 				"of relay dn \"%s\" "
111 				"in \"olcRelay <dn>\"\n",
112 				c->value_dn.bv_val );
113 			Log2( LDAP_DEBUG_CONFIG, LDAP_LEVEL_ERR,
114 				"%s: %s.\n", c->log, c->cr_msg );
115 
116 		} else if ( bd->be_private == c->be->be_private ) {
117 			snprintf( c->cr_msg, sizeof( c->cr_msg),
118 				"relay dn \"%s\" would call self "
119 				"in \"relay <dn>\" line\n",
120 				c->value_dn.bv_val );
121 			Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
122 				"%s: %s.\n", c->log, c->cr_msg );
123 			rc = 1;
124 			goto relay_done;
125 		}
126 
127 		ri->ri_realsuffix = c->value_ndn;
128 		BER_BVZERO( &c->value_ndn );
129 
130 relay_done:;
131 		ch_free( c->value_dn.bv_val );
132 		ch_free( c->value_ndn.bv_val );
133 	}
134 
135 	return rc;
136 }
137 
138 int
139 relay_back_initialize( BackendInfo *bi )
140 {
141 	bi->bi_init = 0;
142 	bi->bi_open = 0;
143 	bi->bi_config = 0;
144 	bi->bi_close = 0;
145 	bi->bi_destroy = 0;
146 
147 	bi->bi_db_init = relay_back_db_init;
148 	bi->bi_db_config = config_generic_wrapper;
149 	bi->bi_db_open = relay_back_db_open;
150 #if 0
151 	bi->bi_db_close = relay_back_db_close;
152 #endif
153 	bi->bi_db_destroy = relay_back_db_destroy;
154 
155 	bi->bi_op_bind = relay_back_op_bind;
156 	bi->bi_op_search = relay_back_op_search;
157 	bi->bi_op_compare = relay_back_op_compare;
158 	bi->bi_op_modify = relay_back_op_modify;
159 	bi->bi_op_modrdn = relay_back_op_modrdn;
160 	bi->bi_op_add = relay_back_op_add;
161 	bi->bi_op_delete = relay_back_op_delete;
162 	bi->bi_extended = relay_back_op_extended;
163 	bi->bi_entry_release_rw = relay_back_entry_release_rw;
164 	bi->bi_entry_get_rw = relay_back_entry_get_rw;
165 	bi->bi_operational = relay_back_operational;
166 	bi->bi_has_subordinates = relay_back_has_subordinates;
167 
168 	bi->bi_cf_ocs = relayocs;
169 
170 	return config_register_schema( relaycfg, relayocs );
171 }
172 
173 int
174 relay_back_db_init( Backend *be, ConfigReply *cr)
175 {
176 	relay_back_info		*ri;
177 
178 	be->be_private = NULL;
179 
180 	ri = (relay_back_info *) ch_calloc( 1, RELAY_INFO_SIZE );
181 	if ( ri == NULL ) {
182  		return -1;
183  	}
184 
185 	ri->ri_bd = NULL;
186 	BER_BVZERO( &ri->ri_realsuffix );
187 	ri->ri_massage = 0;
188 
189 	be->be_cf_ocs = be->bd_info->bi_cf_ocs;
190 
191 	be->be_private = (void *)ri;
192 
193 	return 0;
194 }
195 
196 int
197 relay_back_db_open( Backend *be, ConfigReply *cr )
198 {
199 	relay_back_info		*ri = (relay_back_info *)be->be_private;
200 
201 	assert( ri != NULL );
202 
203 	if ( !BER_BVISNULL( &ri->ri_realsuffix ) ) {
204 		ri->ri_bd = select_backend( &ri->ri_realsuffix, 1 );
205 
206 		/* must be there: it was during config! */
207 		if ( ri->ri_bd == NULL ) {
208 			snprintf( cr->msg, sizeof( cr->msg),
209 				"cannot find database "
210 				"of relay dn \"%s\" "
211 				"in \"olcRelay <dn>\"\n",
212 				ri->ri_realsuffix.bv_val );
213 			Log1( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
214 				"relay_back_db_open: %s.\n", cr->msg );
215 
216 			return 1;
217 		}
218 
219 		/* inherit controls */
220 		AC_MEMCPY( be->bd_self->be_ctrls, ri->ri_bd->be_ctrls, sizeof( be->be_ctrls ) );
221 
222 	} else {
223 		/* inherit all? */
224 		AC_MEMCPY( be->bd_self->be_ctrls, frontendDB->be_ctrls, sizeof( be->be_ctrls ) );
225 	}
226 
227 	return 0;
228 }
229 
230 int
231 relay_back_db_close( Backend *be, ConfigReply *cr )
232 {
233 	return 0;
234 }
235 
236 int
237 relay_back_db_destroy( Backend *be, ConfigReply *cr)
238 {
239 	relay_back_info		*ri = (relay_back_info *)be->be_private;
240 
241 	if ( ri ) {
242 		if ( !BER_BVISNULL( &ri->ri_realsuffix ) ) {
243 			ch_free( ri->ri_realsuffix.bv_val );
244 		}
245 		ch_free( ri );
246 	}
247 
248 	return 0;
249 }
250 
251 #if SLAPD_RELAY == SLAPD_MOD_DYNAMIC
252 
253 /* conditionally define the init_module() function */
254 SLAP_BACKEND_INIT_MODULE( relay )
255 
256 #endif /* SLAPD_RELAY == SLAPD_MOD_DYNAMIC */
257