Imported Upstream version 4.6.2
This commit is contained in:
660
daemons/ipa-slapi-plugins/topology/topology_pre.c
Normal file
660
daemons/ipa-slapi-plugins/topology/topology_pre.c
Normal file
@@ -0,0 +1,660 @@
|
||||
#include "topology.h"
|
||||
|
||||
/* the preoperation plugins check if the managed replication config
|
||||
* is attempted to be directly modified.
|
||||
* This is only allowed for internal operations triggerd by the
|
||||
* topology plugin itself
|
||||
*/
|
||||
|
||||
static int ipa_topo_pre_entry_in_scope(Slapi_PBlock *pb)
|
||||
{
|
||||
Slapi_DN *dn;
|
||||
static Slapi_DN *config_dn = NULL;;
|
||||
|
||||
slapi_pblock_get(pb, SLAPI_TARGET_SDN, &dn);
|
||||
if (config_dn == NULL) {
|
||||
config_dn = slapi_sdn_new_dn_byval("cn=mapping tree,cn=config");
|
||||
/* this rules out entries in regular backends and most of
|
||||
* cn=config entries.
|
||||
*/
|
||||
}
|
||||
return slapi_sdn_issuffix(dn,config_dn);
|
||||
|
||||
}
|
||||
int ipa_topo_is_entry_managed(Slapi_PBlock *pb)
|
||||
{
|
||||
Slapi_Entry *e;
|
||||
char *pi;
|
||||
int op_type;
|
||||
|
||||
if (!ipa_topo_pre_entry_in_scope(pb)) {
|
||||
/* we don't care for general mods, only specific
|
||||
* entries in the mapping tree
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
slapi_pblock_get(pb, SLAPI_OPERATION_TYPE, &op_type);
|
||||
if (op_type == SLAPI_OPERATION_ADD) {
|
||||
slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &e);
|
||||
} else {
|
||||
slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &e);
|
||||
}
|
||||
if (!ipa_topo_util_entry_is_candidate(e)) {
|
||||
/* entry has no objectclass the plugin controls */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* we have to check if the operation is triggered by the
|
||||
* topology plugin itself - allow it
|
||||
*/
|
||||
slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY,&pi);
|
||||
if (pi && 0 == strcasecmp(pi, ipa_topo_get_plugin_id())) {
|
||||
return 0;
|
||||
}
|
||||
/* last check: is the endpoint of the agreement amanaged host ? */
|
||||
if (ipa_topo_util_target_is_managed(e)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
int
|
||||
ipa_topo_is_agmt_attr_restricted(Slapi_PBlock *pb)
|
||||
{
|
||||
LDAPMod **mods;
|
||||
int i;
|
||||
int rc = 0;
|
||||
|
||||
slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
|
||||
for (i = 0; (mods != NULL) && (mods[i] != NULL); i++) {
|
||||
if (ipa_topo_cfg_attr_is_restricted(mods[i]->mod_type)) {
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
int
|
||||
ipa_topo_is_invalid_managed_suffix(Slapi_PBlock *pb)
|
||||
{
|
||||
LDAPMod **mods;
|
||||
int i;
|
||||
int rc = 0;
|
||||
|
||||
slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
|
||||
for (i = 0; (mods != NULL) && (mods[i] != NULL); i++) {
|
||||
if (0 == strcasecmp(mods[i]->mod_type, "ipaReplTopoManagedSuffix")) {
|
||||
switch (mods[i]->mod_op & ~LDAP_MOD_BVALUES) {
|
||||
case LDAP_MOD_DELETE:
|
||||
/* only deletion of specific valuses supported */
|
||||
if (NULL == mods[i]->mod_bvalues || NULL == mods[i]->mod_bvalues[0]) {
|
||||
rc = 1;
|
||||
}
|
||||
break;
|
||||
case LDAP_MOD_ADD:
|
||||
break;
|
||||
case LDAP_MOD_REPLACE:
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
ipa_topo_is_segm_attr_restricted(Slapi_PBlock *pb)
|
||||
{
|
||||
LDAPMod **mods;
|
||||
int i;
|
||||
int rc = 0;
|
||||
|
||||
slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
|
||||
for (i = 0; (mods != NULL) && (mods[i] != NULL); i++) {
|
||||
if ((0 == strcasecmp(mods[i]->mod_type, "ipaReplTopoSegmentDirection")) ||
|
||||
(0 == strcasecmp(mods[i]->mod_type, "ipaReplTopoSegmentLeftNode")) ||
|
||||
(0 == strcasecmp(mods[i]->mod_type, "ipaReplTopoSegmentRightNode"))) {
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* connectivity check for topology
|
||||
* checks if the nodes of a segment would still be connected after
|
||||
* removal of the segments.
|
||||
* For description of the algorithm see design page
|
||||
*/
|
||||
struct node_list {
|
||||
struct node_list *next;
|
||||
char *node;
|
||||
};
|
||||
|
||||
struct node_fanout {
|
||||
struct node_fanout *next;
|
||||
char *node;
|
||||
struct node_list *targets;
|
||||
int visited;
|
||||
};
|
||||
struct node_list *
|
||||
node_list_dup (struct node_list *orig)
|
||||
{
|
||||
struct node_list *dup = NULL;
|
||||
struct node_list *cursor = orig;
|
||||
struct node_list *start_dup = NULL;
|
||||
while (cursor) {
|
||||
if (dup) {
|
||||
dup->next = (struct node_list *)slapi_ch_malloc(sizeof(struct node_list));
|
||||
dup = dup->next;
|
||||
} else {
|
||||
dup = (struct node_list *)slapi_ch_malloc(sizeof(struct node_list));
|
||||
start_dup = dup;
|
||||
}
|
||||
dup->next = NULL;
|
||||
dup->node = slapi_ch_strdup(cursor->node);
|
||||
cursor = cursor->next;
|
||||
}
|
||||
return start_dup;
|
||||
}
|
||||
|
||||
void
|
||||
node_list_free(struct node_list *orig)
|
||||
{
|
||||
struct node_list *cursor = orig;
|
||||
struct node_list *cur_next = NULL;
|
||||
while (cursor) {
|
||||
cur_next = cursor->next;
|
||||
slapi_ch_free_string(&cursor->node);
|
||||
slapi_ch_free((void **)&cursor);
|
||||
cursor = cur_next;
|
||||
}
|
||||
}
|
||||
|
||||
struct node_fanout *
|
||||
ipa_topo_connection_fanout_new (char *from, char *to)
|
||||
{
|
||||
struct node_fanout *new_fanout = (struct node_fanout *)
|
||||
slapi_ch_malloc(sizeof(struct node_fanout));
|
||||
struct node_list *targets = (struct node_list *)
|
||||
slapi_ch_malloc(sizeof(struct node_list));
|
||||
targets->next = NULL;
|
||||
targets->node = slapi_ch_strdup(to);
|
||||
new_fanout->next = NULL;
|
||||
new_fanout->node = slapi_ch_strdup(from);
|
||||
new_fanout->targets = targets;
|
||||
new_fanout->visited = 0;
|
||||
return new_fanout;
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_connection_fanout_free (struct node_fanout *fanout)
|
||||
{
|
||||
struct node_fanout *cursor = fanout;
|
||||
struct node_fanout *cur_next = NULL;
|
||||
while (cursor) {
|
||||
cur_next = cursor->next;
|
||||
slapi_ch_free_string(&cursor->node);
|
||||
node_list_free(cursor->targets);
|
||||
slapi_ch_free((void **)&cursor);
|
||||
cursor = cur_next;
|
||||
}
|
||||
}
|
||||
|
||||
struct node_fanout *
|
||||
ipa_topo_connection_fanout_extend (struct node_fanout *fanout_in, char *from, char *to)
|
||||
{
|
||||
struct node_fanout *cursor;
|
||||
if (fanout_in == NULL) {
|
||||
/* init fanout */
|
||||
return ipa_topo_connection_fanout_new(from,to);
|
||||
}
|
||||
/* extend existing fanout struct */
|
||||
cursor = fanout_in;
|
||||
while (cursor) {
|
||||
if (strcasecmp(cursor->node, from) == 0) break;
|
||||
cursor = cursor->next;
|
||||
}
|
||||
if (cursor) {
|
||||
struct node_list *target = (struct node_list *)
|
||||
slapi_ch_malloc(sizeof(struct node_list));
|
||||
target->next = cursor->targets;
|
||||
target->node = slapi_ch_strdup(to);
|
||||
cursor->targets = target;
|
||||
return fanout_in;
|
||||
} else {
|
||||
cursor = ipa_topo_connection_fanout_new(from,to);
|
||||
cursor->next = fanout_in;
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
struct node_fanout *
|
||||
ipa_topo_connection_fanout(TopoReplica *tconf, TopoReplicaSegment *tseg)
|
||||
{
|
||||
struct node_fanout *fout = NULL;
|
||||
TopoReplicaSegment *segm;
|
||||
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"ipa_topo_connection_fanout for segment: %s\n",tseg->name);
|
||||
/* lock it */
|
||||
TopoReplicaSegmentList *seglist = tconf->repl_segments;
|
||||
while (seglist) {
|
||||
segm = seglist->segm;
|
||||
if (strcasecmp(segm->name, tseg->name)) {
|
||||
if (segm->direct == SEGMENT_LEFT_RIGHT ||
|
||||
segm->direct == SEGMENT_BIDIRECTIONAL ) {
|
||||
fout = ipa_topo_connection_fanout_extend(fout, segm->from, segm->to);
|
||||
}
|
||||
if (segm->direct == SEGMENT_RIGHT_LEFT ||
|
||||
segm->direct == SEGMENT_BIDIRECTIONAL) {
|
||||
fout = ipa_topo_connection_fanout_extend(fout, segm->to, segm->from);
|
||||
}
|
||||
}
|
||||
seglist = seglist->next;
|
||||
}
|
||||
return fout;
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_connection_append(struct node_fanout *fanout, struct node_list *reachable)
|
||||
{
|
||||
struct node_fanout *cursor = fanout;
|
||||
|
||||
while (cursor) {
|
||||
if (strcasecmp(reachable->node, cursor->node) == 0 &&
|
||||
cursor->visited == 0) {
|
||||
struct node_list *tail;
|
||||
struct node_list *extend;
|
||||
cursor->visited = 1;
|
||||
extend = node_list_dup(cursor->targets);
|
||||
tail = reachable;
|
||||
while (tail->next) {
|
||||
tail = tail->next;
|
||||
}
|
||||
tail->next = extend;
|
||||
break;
|
||||
}
|
||||
cursor = cursor->next;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ipa_topo_connection_exists(struct node_fanout *fanout, char* from, char *to)
|
||||
{
|
||||
struct node_list *reachable = NULL;
|
||||
struct node_fanout *cursor = fanout;
|
||||
int connected = 0;
|
||||
/* init reachable nodes */
|
||||
while (cursor) {
|
||||
if (strcasecmp(cursor->node, from) == 0) {
|
||||
cursor->visited = 1;
|
||||
reachable = node_list_dup(cursor->targets);
|
||||
} else {
|
||||
cursor->visited = 0;
|
||||
}
|
||||
cursor = cursor->next;
|
||||
}
|
||||
/* check if target is in reachable nodes, if
|
||||
* not, expand reachables
|
||||
*/
|
||||
if (reachable == NULL) return 0;
|
||||
while (reachable) {
|
||||
if (strcasecmp(reachable->node, to) == 0) {
|
||||
connected = 1;
|
||||
break;
|
||||
}
|
||||
ipa_topo_connection_append(fanout, reachable);
|
||||
reachable = reachable->next;
|
||||
}
|
||||
node_list_free(reachable);
|
||||
return connected;
|
||||
}
|
||||
|
||||
int
|
||||
ipa_topo_check_segment_is_valid(Slapi_PBlock *pb, char **errtxt)
|
||||
{
|
||||
int rc = 0;
|
||||
Slapi_Entry *add_entry;
|
||||
char *pi;
|
||||
|
||||
/* we have to check if the operation is triggered by the
|
||||
* topology plugin itself - allow it
|
||||
*/
|
||||
slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY,&pi);
|
||||
if (pi && 0 == strcasecmp(pi, ipa_topo_get_plugin_id())) {
|
||||
return 0;
|
||||
}
|
||||
slapi_pblock_get(pb,SLAPI_ADD_ENTRY,&add_entry);
|
||||
if (TOPO_SEGMENT_ENTRY != ipa_topo_check_entry_type(add_entry)) {
|
||||
return 0;
|
||||
} else {
|
||||
/* a new segment is added
|
||||
* verify that the segment does not yet exist
|
||||
*/
|
||||
char *leftnode = slapi_entry_attr_get_charptr(add_entry,"ipaReplTopoSegmentLeftNode");
|
||||
char *rightnode = slapi_entry_attr_get_charptr(add_entry,"ipaReplTopoSegmentRightNode");
|
||||
char *dir = slapi_entry_attr_get_charptr(add_entry,"ipaReplTopoSegmentDirection");
|
||||
if (leftnode == NULL || rightnode == NULL || dir == NULL) {
|
||||
*errtxt = slapi_ch_smprintf("Segment definition is incomplete"
|
||||
". Add rejected.\n");
|
||||
rc = 1;
|
||||
} else if (strcasecmp(dir,SEGMENT_DIR_BOTH) && strcasecmp(dir,SEGMENT_DIR_LEFT_ORIGIN) &&
|
||||
strcasecmp(dir,SEGMENT_DIR_RIGHT_ORIGIN)) {
|
||||
*errtxt = slapi_ch_smprintf("Segment has unsupported direction"
|
||||
". Add rejected.\n");
|
||||
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"segment has unknown direction: %s\n", dir);
|
||||
rc = 1;
|
||||
} else if (0 == strcasecmp(leftnode,rightnode)) {
|
||||
*errtxt = slapi_ch_smprintf("Segment is self referential"
|
||||
". Add rejected.\n");
|
||||
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"segment is self referential\n");
|
||||
rc = 1;
|
||||
} else {
|
||||
TopoReplicaSegment *tsegm = NULL;
|
||||
TopoReplica *tconf = ipa_topo_util_get_conf_for_segment(add_entry);
|
||||
if (tconf == NULL ) {
|
||||
*errtxt = slapi_ch_smprintf("Segment configuration suffix not found"
|
||||
". Add rejected.\n");
|
||||
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"topology not configured for segment\n");
|
||||
rc = 1;
|
||||
} else {
|
||||
tsegm = ipa_topo_util_find_segment(tconf, add_entry);
|
||||
}
|
||||
if (tsegm) {
|
||||
*errtxt = slapi_ch_smprintf("Segment already exists in topology"
|
||||
". Add rejected.\n");
|
||||
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"segment to be added does already exist\n");
|
||||
rc = 1;
|
||||
}
|
||||
}
|
||||
slapi_ch_free_string(&leftnode);
|
||||
slapi_ch_free_string(&rightnode);
|
||||
slapi_ch_free_string(&dir);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
ipa_topo_check_segment_updates(Slapi_PBlock *pb)
|
||||
{
|
||||
int rc = 0;
|
||||
Slapi_Entry *mod_entry;
|
||||
char *pi;
|
||||
|
||||
/* we have to check if the operation is triggered by the
|
||||
* topology plugin itself - allow it
|
||||
*/
|
||||
slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY,&pi);
|
||||
if (pi && 0 == strcasecmp(pi, ipa_topo_get_plugin_id())) {
|
||||
return 0;
|
||||
}
|
||||
slapi_pblock_get(pb,SLAPI_MODIFY_EXISTING_ENTRY,&mod_entry);
|
||||
if (TOPO_SEGMENT_ENTRY == ipa_topo_check_entry_type(mod_entry) &&
|
||||
(ipa_topo_is_segm_attr_restricted(pb))) {
|
||||
rc = 1;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
ipa_topo_check_entry_move(Slapi_PBlock *pb)
|
||||
{
|
||||
int rc = 0;
|
||||
int entry_type = TOPO_IGNORE_ENTRY;
|
||||
Slapi_Entry *modrdn_entry;
|
||||
slapi_pblock_get(pb,SLAPI_MODRDN_TARGET_ENTRY,&modrdn_entry);
|
||||
entry_type = ipa_topo_check_entry_type(modrdn_entry);
|
||||
switch (entry_type) {
|
||||
case TOPO_SEGMENT_ENTRY:
|
||||
case TOPO_CONFIG_ENTRY: {
|
||||
Slapi_DN *newsuperior = NULL;
|
||||
slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &newsuperior);
|
||||
if (newsuperior && slapi_sdn_get_dn(newsuperior)) rc = 1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
ipa_topo_check_host_updates(Slapi_PBlock *pb)
|
||||
{
|
||||
int rc = 0;
|
||||
Slapi_Entry *mod_entry;
|
||||
char *pi;
|
||||
|
||||
/* we have to check if the operation is triggered by the
|
||||
* topology plugin itself - allow it
|
||||
*/
|
||||
slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY,&pi);
|
||||
if (pi && 0 == strcasecmp(pi, ipa_topo_get_plugin_id())) {
|
||||
return 0;
|
||||
}
|
||||
slapi_pblock_get(pb,SLAPI_MODIFY_EXISTING_ENTRY,&mod_entry);
|
||||
if (TOPO_HOST_ENTRY == ipa_topo_check_entry_type(mod_entry) &&
|
||||
(ipa_topo_is_invalid_managed_suffix(pb))) {
|
||||
rc = 1;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
ipa_topo_check_topology_disconnect(Slapi_PBlock *pb)
|
||||
{
|
||||
int rc = 1;
|
||||
Slapi_Entry *del_entry;
|
||||
struct node_fanout *fanout = NULL;
|
||||
char *pi;
|
||||
|
||||
/* we have to check if the operation is triggered by the
|
||||
* topology plugin itself - allow it
|
||||
*/
|
||||
slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY,&pi);
|
||||
if (pi && 0 == strcasecmp(pi, ipa_topo_get_plugin_id())) {
|
||||
return 0;
|
||||
}
|
||||
slapi_pblock_get(pb,SLAPI_DELETE_EXISTING_ENTRY,&del_entry);
|
||||
if (TOPO_SEGMENT_ENTRY != ipa_topo_check_entry_type(del_entry)) {
|
||||
return 0;
|
||||
} else {
|
||||
TopoReplica *tconf = ipa_topo_util_get_conf_for_segment(del_entry);
|
||||
if (tconf == NULL) {
|
||||
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"topology not configured for segment\n");
|
||||
rc = 0; /* this segment is not controlled by the plugin */
|
||||
goto done;
|
||||
}
|
||||
TopoReplicaSegment *tsegm = NULL;
|
||||
tsegm = ipa_topo_util_find_segment(tconf, del_entry);
|
||||
if (tsegm == NULL) {
|
||||
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"segment to be deleted does not exist\n");
|
||||
goto done;
|
||||
}
|
||||
if (!ipa_topo_util_segment_is_managed(tconf,tsegm)) {
|
||||
/* not both endpoints are managed servers, delete is ok */
|
||||
rc = 0;
|
||||
goto done;
|
||||
}
|
||||
/* check if removal of segment would break connectivity */
|
||||
fanout = ipa_topo_connection_fanout(tconf, tsegm);
|
||||
if (fanout == NULL) goto done;
|
||||
|
||||
if (ipa_topo_connection_exists(fanout, tsegm->from, tsegm->to) &&
|
||||
ipa_topo_connection_exists(fanout, tsegm->to, tsegm->from)) {
|
||||
rc = 0;
|
||||
}
|
||||
ipa_topo_connection_fanout_free(fanout);
|
||||
}
|
||||
|
||||
done:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
ipa_topo_pre_ignore_op(Slapi_PBlock *pb)
|
||||
{
|
||||
int repl_op = 0;
|
||||
/* changes to cn=config aren't replicated, for changes to
|
||||
* shared topology area checks have been done on master
|
||||
* accepting the operation
|
||||
*/
|
||||
slapi_pblock_get (pb, SLAPI_IS_REPLICATED_OPERATION, &repl_op);
|
||||
return repl_op;
|
||||
}
|
||||
|
||||
int ipa_topo_pre_add(Slapi_PBlock *pb)
|
||||
{
|
||||
int result = SLAPI_PLUGIN_SUCCESS;
|
||||
char *errtxt = NULL;
|
||||
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"--> ipa_topo_pre_add\n");
|
||||
|
||||
if (0 == ipa_topo_get_plugin_active()) {
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"<-- ipa_topo_pre_add - plugin not active\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ipa_topo_pre_ignore_op(pb)) return result;
|
||||
|
||||
if (ipa_topo_is_entry_managed(pb)) {
|
||||
int rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
errtxt = slapi_ch_smprintf("Entry is managed by topology plugin."
|
||||
" Adding of entry not allowed.\n");
|
||||
slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, errtxt);
|
||||
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
|
||||
result = SLAPI_PLUGIN_FAILURE;
|
||||
} else if (ipa_topo_check_segment_is_valid(pb, &errtxt)) {
|
||||
int rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, errtxt);
|
||||
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
|
||||
result = SLAPI_PLUGIN_FAILURE;
|
||||
}
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"<-- ipa_topo_pre_add\n");
|
||||
return result;
|
||||
}
|
||||
int
|
||||
ipa_topo_pre_mod(Slapi_PBlock *pb)
|
||||
{
|
||||
|
||||
int result = SLAPI_PLUGIN_SUCCESS;
|
||||
char *errtxt = NULL;
|
||||
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"--> ipa_topo_pre_mod\n");
|
||||
|
||||
if (0 == ipa_topo_get_plugin_active()) {
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"<-- ipa_topo_pre_mod - plugin not active\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ipa_topo_pre_ignore_op(pb)) return result;
|
||||
|
||||
if (ipa_topo_is_entry_managed(pb)){
|
||||
/* this means it is a replication agreement targeting a managed server
|
||||
* next check is if it tries to modify restricted attributes
|
||||
*/
|
||||
if(ipa_topo_is_agmt_attr_restricted(pb)) {
|
||||
errtxt = slapi_ch_smprintf("Entry and attributes are managed by topology plugin."
|
||||
"No direct modifications allowed.\n");
|
||||
}
|
||||
} else if (ipa_topo_check_segment_updates(pb)) {
|
||||
/* some updates to segments are not supported */
|
||||
errtxt = slapi_ch_smprintf("Modification of connectivity and segment nodes "
|
||||
" is not supported.\n");
|
||||
} else if (ipa_topo_check_host_updates(pb)) {
|
||||
/* some updates to segments are not supported */
|
||||
errtxt = slapi_ch_smprintf("Modification of managed suffixes must explicitely "
|
||||
" list suffix.\n");
|
||||
}
|
||||
if (errtxt) {
|
||||
int rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, errtxt);
|
||||
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
|
||||
result = SLAPI_PLUGIN_FAILURE;
|
||||
}
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"<-- ipa_topo_pre_mod\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
ipa_topo_pre_del(Slapi_PBlock *pb)
|
||||
{
|
||||
int result = SLAPI_PLUGIN_SUCCESS;
|
||||
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"--> ipa_topo_pre_del\n");
|
||||
|
||||
if (0 == ipa_topo_get_plugin_active()) {
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"<-- ipa_topo_pre_del - plugin not active\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ipa_topo_pre_ignore_op(pb) ||
|
||||
ipa_topo_util_is_tombstone_op(pb)) return result;
|
||||
|
||||
if (ipa_topo_is_entry_managed(pb)) {
|
||||
int rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
char *errtxt;
|
||||
errtxt = slapi_ch_smprintf("Entry is managed by topology plugin."
|
||||
"Deletion not allowed.\n");
|
||||
slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, errtxt);
|
||||
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
|
||||
result = SLAPI_PLUGIN_FAILURE;
|
||||
} else if (ipa_topo_check_topology_disconnect(pb)) {
|
||||
int rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
char *errtxt;
|
||||
errtxt = slapi_ch_smprintf("Removal of Segment disconnects topology."
|
||||
"Deletion not allowed.\n");
|
||||
slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, errtxt);
|
||||
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
|
||||
result = SLAPI_PLUGIN_FAILURE;
|
||||
}
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"<-- ipa_topo_pre_del\n");
|
||||
return result;
|
||||
}
|
||||
int
|
||||
ipa_topo_pre_modrdn(Slapi_PBlock *pb)
|
||||
{
|
||||
|
||||
int result = SLAPI_PLUGIN_SUCCESS;
|
||||
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"--> ipa_topo_pre_modrdn\n");
|
||||
|
||||
if (0 == ipa_topo_get_plugin_active()) {
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"<-- ipa_topo_pre_modrdn - plugin not active\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ipa_topo_pre_ignore_op(pb)) return result;
|
||||
|
||||
if (ipa_topo_check_entry_move(pb)){
|
||||
int rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
char *errtxt;
|
||||
errtxt = slapi_ch_smprintf("Moving of a segment or config entry "
|
||||
"to another subtree is not allowed.\n");
|
||||
slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, errtxt);
|
||||
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
|
||||
result = SLAPI_PLUGIN_FAILURE;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user