1 /* config.cpp - ndb backend configuration file routine */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 *
5 * Copyright 2008-2021 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 "slap-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
ndb_cf_gen(ConfigArgs * c)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"
ndb_back_init_cf(BackendInfo * bi)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