From ae14acacc60ba3eaf6d51e826ff23e974ed709da Mon Sep 17 00:00:00 2001 From: Ludwig Krispenz Date: Wed, 4 Sep 2013 16:33:48 +0200 Subject: [PATCH] First attempt to fix ticket #314 --- ldap/servers/plugins/replication/replutil.c | 10 ++-- ldap/servers/slapd/mapping_tree.c | 72 ++++++++++++++++++++++++++--- ldap/servers/slapd/slapi-private.h | 3 ++ 3 files changed, 76 insertions(+), 9 deletions(-) diff --git a/ldap/servers/plugins/replication/replutil.c b/ldap/servers/plugins/replication/replutil.c index d007f6c..0c8296d 100644 --- a/ldap/servers/plugins/replication/replutil.c +++ b/ldap/servers/plugins/replication/replutil.c @@ -814,7 +814,8 @@ repl_set_mtn_state_and_referrals( int repl_chain_on_update(Slapi_PBlock *pb, Slapi_DN * target_dn, char **mtn_be_names, int be_count, - Slapi_DN * node_dn, int *mtn_be_states) + Slapi_DN * node_dn, int *mtn_be_states, + int root_mode) { char * requestor_dn; unsigned long op_type; @@ -943,7 +944,10 @@ repl_chain_on_update(Slapi_PBlock *pb, Slapi_DN * target_dn, "is root: using local backend\n", connid, opid); } #endif - return local_backend; + if (root_mode == CHAIN_ROOT_UPDATE_LOCAL) + return local_backend; + else if (root_mode == CHAIN_ROOT_UPDATE_REJECT) + return (-2); } /* if the operation is a replicated operation @@ -981,7 +985,7 @@ repl_chain_on_update(Slapi_PBlock *pb, Slapi_DN * target_dn, } } - /* all other case (update while not directory manager) : + /* all other cases : * or any normal non replicated client operation while local is disabled (import) : * use the chaining backend */ diff --git a/ldap/servers/slapd/mapping_tree.c b/ldap/servers/slapd/mapping_tree.c index 9336d7c..f7c1d12 100644 --- a/ldap/servers/slapd/mapping_tree.c +++ b/ldap/servers/slapd/mapping_tree.c @@ -47,7 +47,7 @@ /* distribution plugin prototype */ typedef int (* mtn_distrib_fct) (Slapi_PBlock *pb, Slapi_DN * target_dn, - char **mtn_be_names, int be_count, Slapi_DN * mtn_node_dn, int *mtn_be_states); + char **mtn_be_names, int be_count, Slapi_DN * mtn_node_dn, int *mtn_be_states, int rootmode); struct mt_node { @@ -70,6 +70,7 @@ struct mt_node * cn=config, cn=schema and root node */ char * mtn_dstr_plg_lib; /* distribution plugin library name */ char * mtn_dstr_plg_name; /* distribution plugin function name */ + int mtn_dstr_plg_rootmode; /* determines how to process root updates in distribution */ mtn_distrib_fct mtn_dstr_plg; /* pointer to the actual ditribution function */ void *mtn_extension; /* plugins can extend a mapping tree node */ }; @@ -302,7 +303,7 @@ mapping_tree_node_new(Slapi_DN *dn, Slapi_Backend **be, char **backend_names, in int count, int size, char **referral, mapping_tree_node *parent, int state, int private, char *plg_lib, char *plg_fct, - mtn_distrib_fct plg) + mtn_distrib_fct plg, int plg_rootmode) { Slapi_RDN rdn; mapping_tree_node *node; @@ -326,6 +327,7 @@ mapping_tree_node_new(Slapi_DN *dn, Slapi_Backend **be, char **backend_names, in slapi_rdn_done(&rdn); node->mtn_dstr_plg_lib = plg_lib; node->mtn_dstr_plg_name = plg_fct; + node->mtn_dstr_plg_rootmode = plg_rootmode; node->mtn_dstr_plg = plg; slapi_log_error(SLAPI_LOG_TRACE, "mapping_tree", @@ -621,6 +623,7 @@ mapping_tree_entry_add(Slapi_Entry *entry, mapping_tree_node **newnodep ) int * be_states = NULL; char * plugin_funct = NULL; char * plugin_lib = NULL; + int plugin_rootmode = CHAIN_ROOT_UPDATE_REJECT; mtn_distrib_fct plugin = NULL; char **referral = NULL; @@ -729,6 +732,21 @@ mapping_tree_entry_add(Slapi_Entry *entry, mapping_tree_node **newnodep ) continue; } plugin_funct = slapi_ch_strdup(slapi_value_get_string(val)); + } else if (!strcasecmp(type, "nsslapd-distribution-root-update")) { + const char *sval; + slapi_attr_first_value(attr, &val); + if (NULL == val) { + LDAPDebug(LDAP_DEBUG_ANY, "Warning: The nsslapd-distribution-plugin attribute has no value for the mapping tree node %s\n", + slapi_entry_get_dn(entry), 0, 0); + continue; + } + sval = slapi_value_get_string(val); + if (strcmp(sval,"reject") == 0) + plugin_rootmode = CHAIN_ROOT_UPDATE_REJECT; + else if (strcmp(sval,"local") == 0) + plugin_rootmode = CHAIN_ROOT_UPDATE_LOCAL; + else if (strcmp(sval,"chain") == 0) + plugin_rootmode = CHAIN_ROOT_UPDATE_CHAIN; } else if (!strcasecmp(type, MAPPING_TREE_PARENT_ATTRIBUTE)) { Slapi_DN *parent_node_dn = get_parent_from_entry(entry); parent_node = mtn_get_mapping_tree_node_by_entry( @@ -845,7 +863,7 @@ mapping_tree_entry_add(Slapi_Entry *entry, mapping_tree_node **newnodep ) node= mapping_tree_node_new(subtree, be_list, be_names, be_states, be_list_count, be_list_size, referral, parent_node, state, 0 /* Normal node. People can see and change it. */, - plugin_lib, plugin_funct, plugin); + plugin_lib, plugin_funct, plugin, plugin_rootmode); tmp_ndn = slapi_sdn_get_ndn( subtree ); if ( NULL != node && NULL == parent_node && tmp_ndn @@ -1061,6 +1079,7 @@ int mapping_tree_entry_modify_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefor int * be_states = NULL; char * plugin_fct = NULL; char * plugin_lib = NULL; + int plugin_rootmode = CHAIN_ROOT_UPDATE_REJECT; int plugin_flag = 0; mtn_distrib_fct plugin = NULL; @@ -1325,6 +1344,38 @@ int mapping_tree_entry_modify_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefor plugin_flag = 1; } + else if (strcasecmp(mods[i]->mod_type, + "nsslapd-distribution-root-update" ) == 0) + { + if (SLAPI_IS_MOD_REPLACE(mods[i]->mod_op) + || SLAPI_IS_MOD_ADD(mods[i]->mod_op)) + { + const char *sval; + slapi_entry_attr_find(entryAfter, + "nsslapd-distribution-root-update", &attr); + slapi_attr_first_value(attr, &val); + if (NULL == val) { + LDAPDebug(LDAP_DEBUG_ANY, + "Warning: The nsslapd-distribution-root-update attribute" + " has no value for the mapping tree node %s\n", + slapi_entry_get_dn(entryAfter), 0, 0); + plugin_rootmode = CHAIN_ROOT_UPDATE_REJECT; + } else { + sval = slapi_value_get_string(val); + if (strcmp(sval,"reject") == 0) + plugin_rootmode = CHAIN_ROOT_UPDATE_REJECT; + else if (strcmp(sval,"local") == 0) + plugin_rootmode = CHAIN_ROOT_UPDATE_LOCAL; + else if (strcmp(sval,"chain") == 0) + plugin_rootmode = CHAIN_ROOT_UPDATE_CHAIN; + } + } + else if (SLAPI_IS_MOD_DELETE(mods[i]->mod_op)) + { + plugin_rootmode = CHAIN_ROOT_UPDATE_REJECT; /* default */ + } + plugin_flag = 1; + } } /* if distribution plugin has been configured or modified @@ -1371,6 +1422,7 @@ int mapping_tree_entry_modify_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefor if (node->mtn_dstr_plg_name) slapi_ch_free((void **) &node->mtn_dstr_plg_name); node->mtn_dstr_plg_name = plugin_fct; + node->mtn_dstr_plg_rootmode = plugin_rootmode; node->mtn_dstr_plg = plugin; mtn_unlock(); } @@ -1626,7 +1678,7 @@ add_internal_mapping_tree_node(const char *subtree, Slapi_Backend *be, mapping_t MTN_BACKEND, 1, /* The config node is a private node. * People can't see or change it. */ - NULL, NULL, NULL); + NULL, NULL, NULL, 0); /* no distribution */ return node; } @@ -1997,6 +2049,11 @@ Slapi_Backend *slapi_mapping_tree_find_backend_for_sdn(Slapi_DN *sdn) index = mtn_get_be_distributed(pb, target_node, sdn, &flag_stop); slapi_pblock_destroy(pb); /* also frees the operation */ + if (index < 0) { + be = NULL; + goto done; + } + if (target_node->mtn_be[index] == NULL) { target_node->mtn_be[index] = slapi_be_select_by_instance_name( target_node->mtn_backend_names[index]); @@ -2504,7 +2561,7 @@ mtn_get_be_distributed(Slapi_PBlock *pb, mapping_tree_node * target_node, { index = (*target_node->mtn_dstr_plg)(pb, target_sdn, target_node->mtn_backend_names, target_node->mtn_be_count, - target_node->mtn_subtree, target_node->mtn_be_states); + target_node->mtn_subtree, target_node->mtn_be_states, target_node->mtn_dstr_plg_rootmode); if (index == SLAPI_BE_ALL_BACKENDS) { @@ -2521,7 +2578,8 @@ mtn_get_be_distributed(Slapi_PBlock *pb, mapping_tree_node * target_node, " : %d for entry %s at node %s\n", index, slapi_sdn_get_ndn(target_sdn), slapi_sdn_get_ndn(target_node->mtn_subtree)); - index = 0; + if (index > -2) + index = 0; } else { @@ -2622,6 +2680,8 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock *pb, } else { *index = mtn_get_be_distributed(pb, target_node, target_sdn, &flag_stop); + if (*index == -2) + result = LDAP_UNWILLING_TO_PERFORM; } } diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h index e964ae4..9af81e1 100644 --- a/ldap/servers/slapd/slapi-private.h +++ b/ldap/servers/slapd/slapi-private.h @@ -762,6 +762,9 @@ char * slapi_schema_get_superior_name(const char *ocname_or_oid); CSN *dup_global_schema_csn(); /* misc function for the chaining backend */ +#define CHAIN_ROOT_UPDATE_REJECT 0 +#define CHAIN_ROOT_UPDATE_LOCAL 1 +#define CHAIN_ROOT_UPDATE_CHAIN 2 char * slapi_get_rootdn(); /* return the directory manager dn in use */ /* plugin interface to bulk import */ -- 1.7.11.7