1 /* config.c - sock backend configuration file routine */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2007-2014 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
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>.
17 * This work was initially developed by Brian Candler for inclusion
18 * in OpenLDAP Software. Dynamic config support by Howard Chu.
25 #include <ac/string.h>
26 #include <ac/socket.h>
30 #include "back-sock.h"
32 static ConfigDriver bs_cf_gen;
33 static int sock_over_setup();
34 static slap_response sock_over_response;
43 /* The number of overlay-only config attrs */
44 #define NUM_OV_ATTRS 3
46 static ConfigTable bscfg[] = {
47 { "sockops", "ops", 2, 0, 0, ARG_MAGIC|BS_OPS,
48 bs_cf_gen, "( OLcfgDbAt:7.3 NAME 'olcOvSocketOps' "
49 "DESC 'Operation types to forward' "
50 "EQUALITY caseIgnoreMatch "
51 "SYNTAX OMsDirectoryString )", NULL, NULL },
52 { "sockresps", "resps", 2, 0, 0, ARG_MAGIC|BS_RESP,
53 bs_cf_gen, "( OLcfgDbAt:7.4 NAME 'olcOvSocketResps' "
54 "DESC 'Response types to forward' "
55 "EQUALITY caseIgnoreMatch "
56 "SYNTAX OMsDirectoryString )", NULL, NULL },
57 { "socksuffix", "DN", 2, 0, 0, ARG_DN|ARG_QUOTE|ARG_MAGIC|BS_SUFFIX,
58 bs_cf_gen, "( OLcfgDbAt:7.5 NAME 'olcOvSocketSuffix' "
59 "DESC 'DN suffixes to match' "
60 "EQUALITY distinguishedNameMatch "
61 "SYNTAX OMsDN )", NULL, NULL },
63 { "socketpath", "pathname", 2, 2, 0, ARG_STRING|ARG_OFFSET,
64 (void *)offsetof(struct sockinfo, si_sockpath),
65 "( OLcfgDbAt:7.1 NAME 'olcDbSocketPath' "
66 "DESC 'Pathname for Unix domain socket' "
67 "EQUALITY caseExactMatch "
68 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
69 { "extensions", "ext", 2, 0, 0, ARG_MAGIC|BS_EXT,
70 bs_cf_gen, "( OLcfgDbAt:7.2 NAME 'olcDbSocketExtensions' "
71 "DESC 'binddn, peername, or ssf' "
72 "EQUALITY caseIgnoreMatch "
73 "SYNTAX OMsDirectoryString )", NULL, NULL },
77 static ConfigOCs bsocs[] = {
79 "NAME 'olcDbSocketConfig' "
80 "DESC 'Socket backend configuration' "
81 "SUP olcDatabaseConfig "
82 "MUST olcDbSocketPath "
83 "MAY olcDbSocketExtensions )",
84 Cft_Database, bscfg+NUM_OV_ATTRS },
88 static ConfigOCs osocs[] = {
90 "NAME 'olcOvSocketConfig' "
91 "DESC 'Socket overlay configuration' "
92 "SUP olcOverlayConfig "
93 "MUST olcDbSocketPath "
94 "MAY ( olcDbSocketExtensions $ "
95 " olcOvSocketOps $ olcOvSocketResps $ "
96 " olcOvSocketSuffix ) )",
101 #define SOCK_OP_BIND 0x001
102 #define SOCK_OP_UNBIND 0x002
103 #define SOCK_OP_SEARCH 0x004
104 #define SOCK_OP_COMPARE 0x008
105 #define SOCK_OP_MODIFY 0x010
106 #define SOCK_OP_MODRDN 0x020
107 #define SOCK_OP_ADD 0x040
108 #define SOCK_OP_DELETE 0x080
110 #define SOCK_REP_RESULT 0x001
111 #define SOCK_REP_SEARCH 0x002
113 static slap_verbmasks bs_exts[] = {
114 { BER_BVC("binddn"), SOCK_EXT_BINDDN },
115 { BER_BVC("peername"), SOCK_EXT_PEERNAME },
116 { BER_BVC("ssf"), SOCK_EXT_SSF },
117 { BER_BVC("connid"), SOCK_EXT_CONNID },
121 static slap_verbmasks ov_ops[] = {
122 { BER_BVC("bind"), SOCK_OP_BIND },
123 { BER_BVC("unbind"), SOCK_OP_UNBIND },
124 { BER_BVC("search"), SOCK_OP_SEARCH },
125 { BER_BVC("compare"), SOCK_OP_COMPARE },
126 { BER_BVC("modify"), SOCK_OP_MODIFY },
127 { BER_BVC("modrdn"), SOCK_OP_MODRDN },
128 { BER_BVC("add"), SOCK_OP_ADD },
129 { BER_BVC("delete"), SOCK_OP_DELETE },
133 static slap_verbmasks ov_resps[] = {
134 { BER_BVC("result"), SOCK_REP_RESULT },
135 { BER_BVC("search"), SOCK_REP_SEARCH },
140 bs_cf_gen( ConfigArgs *c )
145 if ( c->be && c->table == Cft_Database )
146 si = c->be->be_private;
148 si = c->bi->bi_private;
152 if ( c->op == SLAP_CONFIG_EMIT ) {
155 return mask_to_verbs( bs_exts, si->si_extensions, &c->rvalue_vals );
157 return mask_to_verbs( ov_ops, si->si_ops, &c->rvalue_vals );
159 return mask_to_verbs( ov_resps, si->si_resps, &c->rvalue_vals );
161 value_add( &c->rvalue_vals, si->si_suffix );
162 value_add( &c->rvalue_nvals, si->si_nsuffix );
165 } else if ( c->op == LDAP_MOD_DELETE ) {
169 si->si_extensions = 0;
172 slap_mask_t dels = 0;
173 rc = verbs_to_mask( c->argc, c->argv, bs_exts, &dels );
175 si->si_extensions ^= dels;
183 slap_mask_t dels = 0;
184 rc = verbs_to_mask( c->argc, c->argv, ov_ops, &dels );
194 slap_mask_t dels = 0;
195 rc = verbs_to_mask( c->argc, c->argv, ov_resps, &dels );
197 si->si_resps ^= dels;
202 ber_bvarray_free( si->si_suffix );
203 ber_bvarray_free( si->si_nsuffix );
204 si->si_suffix = NULL;
205 si->si_nsuffix = NULL;
208 ch_free( si->si_suffix[i].bv_val );
209 ch_free( si->si_nsuffix[i].bv_val );
211 si->si_suffix[i] = si->si_suffix[i+1];
212 si->si_nsuffix[i] = si->si_nsuffix[i+1];
214 } while ( !BER_BVISNULL( &si->si_suffix[i] ));
222 return verbs_to_mask( c->argc, c->argv, bs_exts, &si->si_extensions );
224 return verbs_to_mask( c->argc, c->argv, ov_ops, &si->si_ops );
226 return verbs_to_mask( c->argc, c->argv, ov_resps, &si->si_resps );
228 ber_bvarray_add( &si->si_suffix, &c->value_dn );
229 ber_bvarray_add( &si->si_nsuffix, &c->value_ndn );
237 sock_back_init_cf( BackendInfo *bi )
240 bi->bi_cf_ocs = bsocs;
242 rc = config_register_schema( bscfg, bsocs );
244 rc = sock_over_setup();
248 /* sock overlay wrapper */
249 static slap_overinst sockover;
251 static int sock_over_db_init( Backend *be, struct config_reply_s *cr );
252 static int sock_over_db_destroy( Backend *be, struct config_reply_s *cr );
254 static BI_op_bind *sockfuncs[] = {
265 static const int sockopflags[] = {
276 static int sock_over_op(
281 slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
282 void *private = op->o_bd->be_private;
285 slap_operation_t which;
288 case LDAP_REQ_BIND: which = op_bind; break;
289 case LDAP_REQ_UNBIND: which = op_unbind; break;
290 case LDAP_REQ_SEARCH: which = op_search; break;
291 case LDAP_REQ_COMPARE: which = op_compare; break;
292 case LDAP_REQ_MODIFY: which = op_modify; break;
293 case LDAP_REQ_MODRDN: which = op_modrdn; break;
294 case LDAP_REQ_ADD: which = op_add; break;
295 case LDAP_REQ_DELETE: which = op_delete; break;
297 return SLAP_CB_CONTINUE;
299 si = on->on_bi.bi_private;
300 if ( !(si->si_ops & sockopflags[which]))
301 return SLAP_CB_CONTINUE;
303 if ( si->si_nsuffix ) {
305 for ( i=0; !BER_BVISNULL( &si->si_nsuffix[i] ); i++ ) {
306 if ( dnIsSuffix( &op->o_req_ndn, &si->si_nsuffix[i] )) {
312 return SLAP_CB_CONTINUE;
315 op->o_bd->be_private = si;
317 op->o_callback = NULL;
318 sockfuncs[which]( op, rs );
319 op->o_bd->be_private = private;
325 sock_over_response( Operation *op, SlapReply *rs )
327 slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
328 struct sockinfo *si = (struct sockinfo *)on->on_bi.bi_private;
331 if ( rs->sr_type == REP_RESULT ) {
332 if ( !( si->si_resps & SOCK_REP_RESULT ))
333 return SLAP_CB_CONTINUE;
334 } else if ( rs->sr_type == REP_SEARCH ) {
335 if ( !( si->si_resps & SOCK_REP_SEARCH ))
336 return SLAP_CB_CONTINUE;
338 return SLAP_CB_CONTINUE;
340 if (( fp = opensock( si->si_sockpath )) == NULL )
341 return SLAP_CB_CONTINUE;
343 if ( rs->sr_type == REP_RESULT ) {
344 /* write out the result */
345 fprintf( fp, "RESULT\n" );
346 fprintf( fp, "msgid: %ld\n", (long) op->o_msgid );
347 sock_print_conn( fp, op->o_conn, si );
348 fprintf( fp, "code: %d\n", rs->sr_err );
349 if ( rs->sr_matched )
350 fprintf( fp, "matched: %s\n", rs->sr_matched );
352 fprintf( fp, "info: %s\n", rs->sr_text );
354 /* write out the search entry */
356 fprintf( fp, "ENTRY\n" );
357 fprintf( fp, "msgid: %ld\n", (long) op->o_msgid );
358 sock_print_conn( fp, op->o_conn, si );
359 ldap_pvt_thread_mutex_lock( &entry2str_mutex );
360 fprintf( fp, "%s", entry2str( rs->sr_entry, &len ) );
361 ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
366 return SLAP_CB_CONTINUE;
374 sockover.on_bi.bi_type = "sock";
375 sockover.on_bi.bi_db_init = sock_over_db_init;
376 sockover.on_bi.bi_db_destroy = sock_over_db_destroy;
378 sockover.on_bi.bi_op_bind = sock_over_op;
379 sockover.on_bi.bi_op_unbind = sock_over_op;
380 sockover.on_bi.bi_op_search = sock_over_op;
381 sockover.on_bi.bi_op_compare = sock_over_op;
382 sockover.on_bi.bi_op_modify = sock_over_op;
383 sockover.on_bi.bi_op_modrdn = sock_over_op;
384 sockover.on_bi.bi_op_add = sock_over_op;
385 sockover.on_bi.bi_op_delete = sock_over_op;
386 sockover.on_response = sock_over_response;
388 sockover.on_bi.bi_cf_ocs = osocs;
390 rc = config_register_schema( bscfg, osocs );
393 return overlay_register( &sockover );
399 struct config_reply_s *cr
402 slap_overinst *on = (slap_overinst *)be->bd_info;
403 void *private = be->be_private;
404 void *cf_ocs = be->be_cf_ocs;
407 be->be_private = NULL;
408 rc = sock_back_db_init( be, cr );
409 on->on_bi.bi_private = be->be_private;
410 be->be_private = private;
411 be->be_cf_ocs = cf_ocs;
416 sock_over_db_destroy(
418 struct config_reply_s *cr
421 slap_overinst *on = (slap_overinst *)be->bd_info;
422 void *private = be->be_private;
425 be->be_private = on->on_bi.bi_private;
426 rc = sock_back_db_destroy( be, cr );
427 on->on_bi.bi_private = be->be_private;
428 be->be_private = private;