1 /* config.cpp - ndb backend configuration file routine */
2 /* OpenLDAP: pkg/ldap/servers/slapd/back-ndb/config.cpp,v 1.3.2.3 2010/04/13 20:23:34 kurt Exp */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2008-2010 The OpenLDAP Foundation.
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 Howard Chu for inclusion
18  * in OpenLDAP Software. This work was sponsored by MySQL.
19  */
20 
21 #include "portable.h"
22 #include "lutil.h"
23 
24 #include "back-ndb.h"
25 
26 #include "config.h"
27 
28 extern "C" {
29 	static ConfigDriver ndb_cf_gen;
30 };
31 
32 enum {
33 	NDB_ATLEN = 1,
34 	NDB_ATSET,
35 	NDB_INDEX,
36 	NDB_ATBLOB
37 };
38 
39 static ConfigTable ndbcfg[] = {
40 	{ "dbhost", "hostname", 2, 2, 0, ARG_STRING|ARG_OFFSET,
41 		(void *)offsetof(struct ndb_info, ni_hostname),
42 		"( OLcfgDbAt:6.1 NAME 'olcDbHost' "
43 			"DESC 'Hostname of SQL server' "
44 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
45 	{ "dbname", "name", 2, 2, 0, ARG_STRING|ARG_OFFSET,
46 		(void *)offsetof(struct ndb_info, ni_dbname),
47 		"( OLcfgDbAt:6.2 NAME 'olcDbName' "
48 			"DESC 'Name of SQL database' "
49 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
50 	{ "dbuser", "username", 2, 2, 0, ARG_STRING|ARG_OFFSET,
51 		(void *)offsetof(struct ndb_info, ni_username),
52 		"( OLcfgDbAt:6.3 NAME 'olcDbUser' "
53 			"DESC 'Username for SQL session' "
54 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
55 	{ "dbpass", "password", 2, 2, 0, ARG_STRING|ARG_OFFSET,
56 		(void *)offsetof(struct ndb_info, ni_password),
57 		"( OLcfgDbAt:6.4 NAME 'olcDbPass' "
58 			"DESC 'Password for SQL session' "
59 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
60 	{ "dbport", "port", 2, 2, 0, ARG_UINT|ARG_OFFSET,
61 		(void *)offsetof(struct ndb_info, ni_port),
62 		"( OLcfgDbAt:6.5 NAME 'olcDbPort' "
63 			"DESC 'Port number of SQL server' "
64 			"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
65 	{ "dbsocket", "path", 2, 2, 0, ARG_STRING|ARG_OFFSET,
66 		(void *)offsetof(struct ndb_info, ni_socket),
67 		"( OLcfgDbAt:6.6 NAME 'olcDbSocket' "
68 			"DESC 'Local socket path of SQL server' "
69 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
70 	{ "dbflag", "flag", 2, 2, 0, ARG_LONG|ARG_OFFSET,
71 		(void *)offsetof(struct ndb_info, ni_clflag),
72 		"( OLcfgDbAt:6.7 NAME 'olcDbFlag' "
73 			"DESC 'Flags for SQL session' "
74 			"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
75 	{ "dbconnect", "hostname", 2, 2, 0, ARG_STRING|ARG_OFFSET,
76 		(void *)offsetof(struct ndb_info, ni_connectstr),
77 		"( OLcfgDbAt:6.8 NAME 'olcDbConnect' "
78 			"DESC 'Hostname of NDB server' "
79 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
80 	{ "dbconnections", "number", 2, 2, 0, ARG_INT|ARG_OFFSET,
81 		(void *)offsetof(struct ndb_info, ni_nconns),
82 		"( OLcfgDbAt:6.9 NAME 'olcDbConnections' "
83 			"DESC 'Number of cluster connections to open' "
84 			"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
85 	{ "attrlen", "attr> <len", 3, 3, 0, ARG_MAGIC|NDB_ATLEN,
86 		(void *)ndb_cf_gen,
87 		"( OLcfgDbAt:6.10 NAME 'olcNdbAttrLen' "
88 			"DESC 'Column length of a specific attribute' "
89 			"EQUALITY caseIgnoreMatch "
90 			"SYNTAX OMsDirectoryString )", NULL, NULL },
91 	{ "attrset", "set> <attrs", 3, 3, 0, ARG_MAGIC|NDB_ATSET,
92 		(void *)ndb_cf_gen,
93 		"( OLcfgDbAt:6.11 NAME 'olcNdbAttrSet' "
94 			"DESC 'Set of common attributes' "
95 			"EQUALITY caseIgnoreMatch "
96 			"SYNTAX OMsDirectoryString )", NULL, NULL },
97 	{ "index", "attr", 2, 2, 0, ARG_MAGIC|NDB_INDEX,
98 		(void *)ndb_cf_gen, "( OLcfgDbAt:0.2 NAME 'olcDbIndex' "
99 		"DESC 'Attribute to index' "
100 		"EQUALITY caseIgnoreMatch "
101 		"SYNTAX OMsDirectoryString )", NULL, NULL },
102 	{ "attrblob", "attr", 2, 2, 0, ARG_MAGIC|NDB_ATBLOB,
103 		(void *)ndb_cf_gen, "( OLcfgDbAt:6.12 NAME 'olcNdbAttrBlob' "
104 		"DESC 'Attribute to treat as a BLOB' "
105 		"EQUALITY caseIgnoreMatch "
106 		"SYNTAX OMsDirectoryString )", NULL, NULL },
107 	{ "directory", "dir", 2, 2, 0, ARG_IGNORED,
108 		NULL, "( OLcfgDbAt:0.1 NAME 'olcDbDirectory' "
109 			"DESC 'Dummy keyword' "
110 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
111 	{ NULL, NULL, 0, 0, 0, ARG_IGNORED,
112 		NULL, NULL, NULL, NULL }
113 };
114 
115 static ConfigOCs ndbocs[] = {
116 	{
117 		"( OLcfgDbOc:6.2 "
118 		"NAME 'olcNdbConfig' "
119 		"DESC 'NDB backend configuration' "
120 		"SUP olcDatabaseConfig "
121 		"MUST ( olcDbHost $ olcDbName $ olcDbConnect ) "
122 		"MAY ( olcDbUser $ olcDbPass $ olcDbPort $ olcDbSocket $ "
123 		"olcDbFlag $ olcDbConnections $ olcNdbAttrLen $ "
124 		"olcDbIndex $ olcNdbAttrSet $ olcNdbAttrBlob ) )",
125 			Cft_Database, ndbcfg },
126 	{ NULL, Cft_Abstract, NULL }
127 };
128 
129 static int
130 ndb_cf_gen( ConfigArgs *c )
131 {
132 	struct ndb_info *ni = (struct ndb_info *)c->be->be_private;
133 	int i, rc;
134 	NdbAttrInfo *ai;
135 	NdbOcInfo *oci;
136 	ListNode *ln, **l2;
137 	struct berval bv, *bva;
138 
139 	if ( c->op == SLAP_CONFIG_EMIT ) {
140 		char buf[BUFSIZ];
141 		rc = 0;
142 		bv.bv_val = buf;
143 		switch( c->type ) {
144 		case NDB_ATLEN:
145 			if ( ni->ni_attrlens ) {
146 				for ( ln = ni->ni_attrlens; ln; ln=ln->ln_next ) {
147 					ai = (NdbAttrInfo *)ln->ln_data;
148 					bv.bv_len = snprintf( buf, sizeof(buf),
149 						"%s %d", ai->na_name.bv_val,
150 							ai->na_len );
151 					value_add_one( &c->rvalue_vals, &bv );
152 				}
153 			} else {
154 				rc = 1;
155 			}
156 			break;
157 
158 		case NDB_ATSET:
159 			if ( ni->ni_attrsets ) {
160 				char *ptr, *end = buf+sizeof(buf);
161 				for ( ln = ni->ni_attrsets; ln; ln=ln->ln_next ) {
162 					oci = (NdbOcInfo *)ln->ln_data;
163 					ptr = lutil_strcopy( buf, oci->no_name.bv_val );
164 					*ptr++ = ' ';
165 					for ( i=0; i<oci->no_nattrs; i++ ) {
166 						if ( end - ptr < oci->no_attrs[i]->na_name.bv_len+1 )
167 							break;
168 						if ( i )
169 							*ptr++ = ',';
170 						ptr = lutil_strcopy(ptr,
171 							oci->no_attrs[i]->na_name.bv_val );
172 					}
173 					bv.bv_len = ptr - buf;
174 					value_add_one( &c->rvalue_vals, &bv );
175 				}
176 			} else {
177 				rc = 1;
178 			}
179 			break;
180 
181 		case NDB_INDEX:
182 			if ( ni->ni_attridxs ) {
183 				for ( ln = ni->ni_attridxs; ln; ln=ln->ln_next ) {
184 					ai = (NdbAttrInfo *)ln->ln_data;
185 					value_add_one( &c->rvalue_vals, &ai->na_name );
186 				}
187 			} else {
188 				rc = 1;
189 			}
190 			break;
191 
192 		case NDB_ATBLOB:
193 			if ( ni->ni_attrblobs ) {
194 				for ( ln = ni->ni_attrblobs; ln; ln=ln->ln_next ) {
195 					ai = (NdbAttrInfo *)ln->ln_data;
196 					value_add_one( &c->rvalue_vals, &ai->na_name );
197 				}
198 			} else {
199 				rc = 1;
200 			}
201 			break;
202 
203 		}
204 		return rc;
205 	} else if ( c->op == LDAP_MOD_DELETE ) { /* FIXME */
206 		rc = 0;
207 		switch( c->type ) {
208 		case NDB_INDEX:
209 			if ( c->valx == -1 ) {
210 
211 				/* delete all */
212 
213 			} else {
214 
215 			}
216 			break;
217 		}
218 		return rc;
219 	}
220 
221 	switch( c->type ) {
222 	case NDB_ATLEN:
223 		ber_str2bv( c->argv[1], 0, 0, &bv );
224 		ai = ndb_ai_get( ni, &bv );
225 		if ( !ai ) {
226 			snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: invalid attr %s",
227 				c->log, c->argv[1] );
228 			Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg, 0, 0 );
229 			return -1;
230 		}
231 		for ( ln = ni->ni_attrlens; ln; ln = ln->ln_next ) {
232 			if ( ln->ln_data == (void *)ai ) {
233 				snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: attr len already set for %s",
234 					c->log, c->argv[1] );
235 				Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg, 0, 0 );
236 				return -1;
237 			}
238 		}
239 		ai->na_len = atoi( c->argv[2] );
240 		ai->na_flag |= NDB_INFO_ATLEN;
241 		ln = (ListNode *)ch_malloc( sizeof(ListNode));
242 		ln->ln_data = ai;
243 		ln->ln_next = NULL;
244 		for ( l2 = &ni->ni_attrlens; *l2; l2 = &(*l2)->ln_next );
245 		*l2 = ln;
246 		break;
247 
248 	case NDB_INDEX:
249 		ber_str2bv( c->argv[1], 0, 0, &bv );
250 		ai = ndb_ai_get( ni, &bv );
251 		if ( !ai ) {
252 			snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: invalid attr %s",
253 				c->log, c->argv[1] );
254 			Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg, 0, 0 );
255 			return -1;
256 		}
257 		for ( ln = ni->ni_attridxs; ln; ln = ln->ln_next ) {
258 			if ( ln->ln_data == (void *)ai ) {
259 				snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: attr index already set for %s",
260 					c->log, c->argv[1] );
261 				Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg, 0, 0 );
262 				return -1;
263 			}
264 		}
265 		ai->na_flag |= NDB_INFO_INDEX;
266 		ln = (ListNode *)ch_malloc( sizeof(ListNode));
267 		ln->ln_data = ai;
268 		ln->ln_next = NULL;
269 		for ( l2 = &ni->ni_attridxs; *l2; l2 = &(*l2)->ln_next );
270 		*l2 = ln;
271 		break;
272 
273 	case NDB_ATSET:
274 		ber_str2bv( c->argv[1], 0, 0, &bv );
275 		bva = ndb_str2bvarray( c->argv[2], strlen( c->argv[2] ), ',', NULL );
276 		rc = ndb_aset_get( ni, &bv, bva, &oci );
277 		ber_bvarray_free( bva );
278 		if ( rc ) {
279 			if ( rc == LDAP_ALREADY_EXISTS ) {
280 				snprintf( c->cr_msg, sizeof( c->cr_msg ),
281 					"%s: attrset %s already defined",
282 					c->log, c->argv[1] );
283 			} else {
284 				snprintf( c->cr_msg, sizeof( c->cr_msg ),
285 					"%s: invalid attrset %s (%d)",
286 					c->log, c->argv[1], rc );
287 			}
288 			Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg, 0, 0 );
289 			return -1;
290 		}
291 		ln = (ListNode *)ch_malloc( sizeof(ListNode));
292 		ln->ln_data = oci;
293 		ln->ln_next = NULL;
294 		for ( l2 = &ni->ni_attrsets; *l2; l2 = &(*l2)->ln_next );
295 		*l2 = ln;
296 		break;
297 
298 	case NDB_ATBLOB:
299 		ber_str2bv( c->argv[1], 0, 0, &bv );
300 		ai = ndb_ai_get( ni, &bv );
301 		if ( !ai ) {
302 			snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: invalid attr %s",
303 				c->log, c->argv[1] );
304 			Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg, 0, 0 );
305 			return -1;
306 		}
307 		for ( ln = ni->ni_attrblobs; ln; ln = ln->ln_next ) {
308 			if ( ln->ln_data == (void *)ai ) {
309 				snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: attr blob already set for %s",
310 					c->log, c->argv[1] );
311 				Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg, 0, 0 );
312 				return -1;
313 			}
314 		}
315 		ai->na_flag |= NDB_INFO_ATBLOB;
316 		ln = (ListNode *)ch_malloc( sizeof(ListNode));
317 		ln->ln_data = ai;
318 		ln->ln_next = NULL;
319 		for ( l2 = &ni->ni_attrblobs; *l2; l2 = &(*l2)->ln_next );
320 		*l2 = ln;
321 		break;
322 
323 	}
324 	return 0;
325 }
326 
327 extern "C"
328 int ndb_back_init_cf( BackendInfo *bi )
329 {
330 	bi->bi_cf_ocs = ndbocs;
331 
332 	return config_register_schema( ndbcfg, ndbocs );
333 }
334