mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-01-25 15:46:30 -06:00
a76d4402a6
A managed host may handle several ipaReplTopoManagedSuffix. Removing (from the topology) such host, loops over the replicated suffixes array to retrieve, in the hosts list, the host record and delete it. The problem is that a variable used to manage a hosts list is not reset when looking at the next suffix. That will messup the lists, keeping freed elements in the lists. The fix is to reset the variable inside the replicated suffix loop https://fedorahosted.org/freeipa/ticket/5977 Reviewed-By: Ludwig Krispenz <lkrispen@redhat.com>
894 lines
24 KiB
C
894 lines
24 KiB
C
|
|
#include "topology.h"
|
|
|
|
/* two static data structures to hold the
|
|
* plugin configuration and the information
|
|
* stored in the shared tree.
|
|
* They will be initialized at plugin init/start,
|
|
* updated when the shared config is modified
|
|
* and accessed via set/get functions
|
|
*/
|
|
static TopoPluginConf topo_plugin_conf = {0};
|
|
static TopoReplicaConf topo_shared_conf = {0};
|
|
static int ipa_domain_level = 0;
|
|
static int topo_min_domain_level = 1;
|
|
|
|
char *ipa_topo_plugin_managed_attrs[] = {
|
|
"nsds5ReplicaStripAttrs",
|
|
"nsds5ReplicatedAttributeList",
|
|
"nsDS5ReplicatedAttributeListTotal",
|
|
"nsds5BeginReplicaRefresh",
|
|
"nsds5replicaTimeout",
|
|
"nsds5ReplicaEnabled",
|
|
"nsds5replicaSessionPauseTime",
|
|
"nsds5replicabinddn",
|
|
"nsds5replicacredentials",
|
|
"nsds5replicatransportinfo",
|
|
"nsds5replicabindmethod",
|
|
NULL };
|
|
|
|
/* subset of attrs which can only be modified via
|
|
* modification of segments in the shared tree.
|
|
* Other attributes still can be directly modified
|
|
* eg to reinit a replica or change bind method and
|
|
* credentials.
|
|
* This is currently needed to make ipa-replica-install work
|
|
*/
|
|
char *ipa_topo_plugin_restricted_attrs[] = {
|
|
"nsds5ReplicaStripAttrs",
|
|
"nsds5ReplicatedAttributeList",
|
|
"nsDS5ReplicatedAttributeListTotal",
|
|
"nsds5replicaTimeout",
|
|
"nsds5replicaSessionPauseTime",
|
|
NULL };
|
|
|
|
void *
|
|
ipa_topo_get_plugin_id(void)
|
|
{
|
|
return topo_plugin_conf.identity;
|
|
}
|
|
|
|
char *
|
|
ipa_topo_get_plugin_hostname(void)
|
|
{
|
|
return topo_plugin_conf.hostname;
|
|
}
|
|
|
|
char **
|
|
ipa_topo_get_plugin_managed_attrs(void)
|
|
{
|
|
return topo_plugin_conf.managed_attrs;
|
|
}
|
|
|
|
char **
|
|
ipa_topo_get_plugin_restricted_attrs(void)
|
|
{
|
|
return topo_plugin_conf.restricted_attrs;
|
|
}
|
|
|
|
char *
|
|
ipa_topo_get_plugin_shared_config(void)
|
|
{
|
|
return topo_plugin_conf.shared_config_base;
|
|
}
|
|
char *
|
|
ipa_topo_get_plugin_shared_topo(void)
|
|
{
|
|
return topo_plugin_conf.shared_topo;
|
|
}
|
|
|
|
Slapi_DN *
|
|
ipa_topo_get_plugin_shared_topo_dn(void)
|
|
{
|
|
return topo_plugin_conf.shared_topo_sdn;
|
|
}
|
|
|
|
char *
|
|
ipa_topo_get_domain_level_entry(void)
|
|
{
|
|
return topo_plugin_conf.domain_level;
|
|
}
|
|
|
|
Slapi_DN *
|
|
ipa_topo_get_domain_level_entry_dn(void)
|
|
{
|
|
return topo_plugin_conf.domain_level_sdn;
|
|
}
|
|
|
|
int
|
|
ipa_topo_get_min_domain_level(void)
|
|
{
|
|
return topo_min_domain_level;
|
|
}
|
|
|
|
int
|
|
ipa_topo_get_domain_level(void)
|
|
{
|
|
return ipa_domain_level;
|
|
}
|
|
|
|
char *
|
|
ipa_topo_get_plugin_shared_hosts(void)
|
|
{
|
|
return topo_plugin_conf.shared_hosts;
|
|
}
|
|
|
|
Slapi_DN *
|
|
ipa_topo_get_plugin_shared_hosts_dn(void)
|
|
{
|
|
return topo_plugin_conf.shared_hosts_sdn;
|
|
}
|
|
|
|
char *
|
|
ipa_topo_get_plugin_shared_bindgroup(void)
|
|
{
|
|
return topo_plugin_conf.shared_bindgroup;
|
|
}
|
|
|
|
Slapi_DN *
|
|
ipa_topo_get_plugin_shared_bindgroup_dn(void)
|
|
{
|
|
return topo_plugin_conf.shared_bindgroup_sdn;
|
|
}
|
|
char **
|
|
ipa_topo_get_plugin_replica_root(void)
|
|
{
|
|
return topo_plugin_conf.shared_replica_root;
|
|
}
|
|
|
|
int
|
|
ipa_topo_get_plugin_version_major(void)
|
|
{
|
|
return topo_plugin_conf.version_major;
|
|
}
|
|
|
|
int
|
|
ipa_topo_get_plugin_version_minor(void)
|
|
{
|
|
return topo_plugin_conf.version_minor;
|
|
}
|
|
|
|
int
|
|
ipa_topo_get_plugin_startup_delay(void)
|
|
{
|
|
return topo_plugin_conf.startup_delay;
|
|
}
|
|
|
|
void
|
|
ipa_topo_set_plugin_id(void *plg_id)
|
|
{
|
|
topo_plugin_conf.identity = plg_id;
|
|
}
|
|
|
|
void
|
|
ipa_topo_set_plugin_active(int state)
|
|
{
|
|
topo_plugin_conf.activated = state;
|
|
}
|
|
int
|
|
ipa_topo_get_plugin_active(void)
|
|
{
|
|
return topo_plugin_conf.activated;
|
|
}
|
|
|
|
|
|
void
|
|
ipa_topo_set_post_init(int state)
|
|
{
|
|
topo_plugin_conf.post_init = state;
|
|
}
|
|
int
|
|
ipa_topo_get_post_init(void)
|
|
{
|
|
return topo_plugin_conf.post_init;
|
|
}
|
|
|
|
void
|
|
ipa_topo_set_plugin_shared_config(char *cfg)
|
|
{
|
|
char *topo;
|
|
char *hosts;
|
|
char *domain_level;
|
|
topo_plugin_conf.shared_config_base = cfg;
|
|
topo = slapi_ch_smprintf("%s,%s","cn=topology",cfg);
|
|
hosts = slapi_ch_smprintf("%s,%s","cn=masters",cfg);
|
|
domain_level = slapi_ch_smprintf("%s,%s","cn=domain level",cfg);
|
|
topo_plugin_conf.shared_topo = topo;
|
|
topo_plugin_conf.shared_topo_sdn = slapi_sdn_new_normdn_byref(topo);
|
|
topo_plugin_conf.shared_hosts = hosts;
|
|
topo_plugin_conf.shared_hosts_sdn = slapi_sdn_new_normdn_byref(hosts);
|
|
topo_plugin_conf.domain_level = domain_level;
|
|
topo_plugin_conf.domain_level_sdn = slapi_sdn_new_normdn_byref(domain_level);
|
|
|
|
}
|
|
|
|
void
|
|
ipa_topo_set_plugin_shared_bindgroup(char *bindgroup)
|
|
{
|
|
topo_plugin_conf.shared_bindgroup = bindgroup;
|
|
topo_plugin_conf.shared_bindgroup_sdn = slapi_sdn_new_normdn_byref(bindgroup);
|
|
}
|
|
|
|
void
|
|
ipa_topo_set_domain_level(char *level)
|
|
{
|
|
if (level == NULL) {
|
|
ipa_domain_level = 0;
|
|
return;
|
|
}
|
|
|
|
ipa_domain_level = atoi(level);
|
|
}
|
|
|
|
void
|
|
ipa_topo_set_plugin_hostname(char *hostname)
|
|
{
|
|
topo_plugin_conf.hostname = hostname;
|
|
}
|
|
|
|
#define TOPO_PLUGIN_DEFAULT_STARTUP_DELAY 20
|
|
void
|
|
ipa_topo_set_plugin_startup_delay(char *delay)
|
|
{
|
|
if (delay) {
|
|
topo_plugin_conf.startup_delay = atoi(delay);
|
|
} else {
|
|
topo_plugin_conf.startup_delay = TOPO_PLUGIN_DEFAULT_STARTUP_DELAY;
|
|
}
|
|
}
|
|
|
|
void
|
|
ipa_topo_set_plugin_version(char *version)
|
|
{
|
|
char *minor;
|
|
|
|
if ( version == NULL) {
|
|
topo_plugin_conf.version_major = 0;
|
|
topo_plugin_conf.version_minor = 0;
|
|
return;
|
|
}
|
|
|
|
minor = strchr(version,'.');
|
|
if (minor) {
|
|
*minor = '\0';
|
|
topo_plugin_conf.version_minor = atoi(++minor);
|
|
} else {
|
|
topo_plugin_conf.version_minor = 0;
|
|
}
|
|
topo_plugin_conf.version_major = atoi(version);
|
|
}
|
|
|
|
void
|
|
ipa_topo_init_shared_config(void)
|
|
{
|
|
topo_shared_conf.allhosts = NULL;
|
|
topo_shared_conf.replicas = NULL;
|
|
topo_shared_conf.conf_lock = slapi_new_mutex();
|
|
}
|
|
|
|
void
|
|
ipa_topo_set_plugin_managed_attrs(char **attrs)
|
|
{
|
|
if (attrs) {
|
|
topo_plugin_conf.managed_attrs = attrs;
|
|
} else {
|
|
topo_plugin_conf.managed_attrs = ipa_topo_plugin_managed_attrs;
|
|
}
|
|
}
|
|
|
|
void
|
|
ipa_topo_set_plugin_restricted_attrs(char **attrs)
|
|
{
|
|
if (attrs) {
|
|
topo_plugin_conf.restricted_attrs = attrs;
|
|
} else {
|
|
topo_plugin_conf.restricted_attrs = ipa_topo_plugin_restricted_attrs;
|
|
}
|
|
}
|
|
|
|
int
|
|
ipa_topo_cfg_plugin_suffix_is_managed(const char *be_suffix) {
|
|
|
|
int i = 0;
|
|
char **shared_replica_root = ipa_topo_get_plugin_replica_root();
|
|
|
|
while (shared_replica_root[i]) {
|
|
if (0 == strcasecmp(shared_replica_root[i], be_suffix)) return 1;
|
|
i++;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
ipa_topo_cfg_attr_is_restricted(char *type)
|
|
{
|
|
int i;
|
|
int rc = 0;
|
|
char **rattrs = ipa_topo_get_plugin_restricted_attrs();
|
|
for (i=0; rattrs[i]; i++) {
|
|
if(0 == strcasecmp(rattrs[i], type)) {
|
|
rc = 1;
|
|
break;
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
void
|
|
ipa_topo_set_plugin_replica_root(char **root)
|
|
{
|
|
topo_plugin_conf.shared_replica_root = root;
|
|
}
|
|
|
|
int
|
|
ipa_topo_init_plugin_config(Slapi_PBlock * pb)
|
|
{
|
|
Slapi_Entry *plugin_entry = NULL;
|
|
char *hostname;
|
|
char *config_base;
|
|
char *startup_delay;
|
|
char *plugin_version;
|
|
char *bindgroup;
|
|
char **replica_root;
|
|
|
|
/* get the local hostname */
|
|
hostname = ipa_topo_util_get_pluginhost();
|
|
if (hostname == NULL) {
|
|
/* log error */
|
|
return -1;
|
|
} else {
|
|
ipa_topo_set_plugin_hostname(hostname);
|
|
}
|
|
/* get the args */
|
|
/* slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, &plugin_entry); */
|
|
slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &plugin_entry);
|
|
|
|
if(plugin_entry == NULL){
|
|
return -1;
|
|
}
|
|
|
|
ipa_topo_set_plugin_active(0);
|
|
|
|
config_base = slapi_entry_attr_get_charptr(plugin_entry,
|
|
CONFIG_ATTR_SHARED_BASE);
|
|
if(config_base){
|
|
ipa_topo_set_plugin_shared_config(config_base);
|
|
}
|
|
|
|
replica_root = slapi_entry_attr_get_charray(plugin_entry,
|
|
CONFIG_ATTR_REPLICA_ROOT);
|
|
if(replica_root){
|
|
ipa_topo_set_plugin_replica_root(replica_root);
|
|
}
|
|
|
|
bindgroup = slapi_entry_attr_get_charptr(plugin_entry,
|
|
CONFIG_ATTR_SHARED_BINDDNGROUP);
|
|
if(bindgroup){
|
|
ipa_topo_set_plugin_shared_bindgroup(bindgroup);
|
|
}
|
|
|
|
startup_delay = slapi_entry_attr_get_charptr(plugin_entry,
|
|
CONFIG_ATTR_STARTUP_DELAY);
|
|
ipa_topo_set_plugin_startup_delay(startup_delay);
|
|
slapi_ch_free_string(&startup_delay);
|
|
|
|
plugin_version = slapi_entry_attr_get_charptr(plugin_entry,
|
|
CONFIG_ATTR_PLUGIN_VERSION);
|
|
ipa_topo_set_plugin_version(plugin_version);
|
|
slapi_ch_free_string(&plugin_version);
|
|
|
|
ipa_topo_util_set_domain_level();
|
|
|
|
ipa_topo_util_check_plugin_active();
|
|
|
|
|
|
ipa_topo_set_plugin_managed_attrs(NULL); /* use defaults */
|
|
ipa_topo_set_plugin_restricted_attrs(NULL); /* use defaults */
|
|
return 0;
|
|
|
|
}
|
|
|
|
void
|
|
ipa_topo_free_plugin_config(void)
|
|
{
|
|
slapi_destroy_mutex(topo_plugin_conf.plg_lock);
|
|
slapi_ch_free((void **)topo_plugin_conf.identity);
|
|
slapi_ch_free_string(&topo_plugin_conf.hostname);
|
|
slapi_ch_free_string(&topo_plugin_conf.shared_config_base);
|
|
slapi_ch_free_string(&topo_plugin_conf.shared_topo);
|
|
slapi_sdn_free(&topo_plugin_conf.shared_topo_sdn);
|
|
slapi_ch_free_string(&topo_plugin_conf.shared_hosts);
|
|
slapi_sdn_free(&topo_plugin_conf.shared_hosts_sdn);
|
|
slapi_ch_free_string(&topo_plugin_conf.shared_bindgroup);
|
|
slapi_sdn_free(&topo_plugin_conf.shared_bindgroup_sdn);
|
|
slapi_ch_free_string(&topo_plugin_conf.domain_level);
|
|
slapi_sdn_free(&topo_plugin_conf.domain_level_sdn);
|
|
slapi_ch_array_free(topo_plugin_conf.shared_replica_root);
|
|
if (ipa_topo_plugin_managed_attrs != topo_plugin_conf.managed_attrs)
|
|
slapi_ch_array_free(topo_plugin_conf.managed_attrs);
|
|
if (ipa_topo_plugin_restricted_attrs != topo_plugin_conf.restricted_attrs)
|
|
slapi_ch_array_free(topo_plugin_conf.restricted_attrs);
|
|
}
|
|
|
|
void
|
|
ipa_topo_lock_conf(void)
|
|
{
|
|
slapi_lock_mutex(topo_shared_conf.conf_lock);
|
|
}
|
|
|
|
void
|
|
ipa_topo_unlock_conf(void)
|
|
{
|
|
slapi_unlock_mutex(topo_shared_conf.conf_lock);
|
|
}
|
|
|
|
int
|
|
ipa_topo_acquire_startup_inprogress(void)
|
|
{
|
|
int acquired = 0;
|
|
slapi_lock_mutex(topo_shared_conf.conf_lock);
|
|
if (topo_shared_conf.startup_inprogress == 0 ) {
|
|
topo_shared_conf.startup_inprogress = 1;
|
|
acquired = 1;
|
|
}
|
|
slapi_unlock_mutex(topo_shared_conf.conf_lock);
|
|
return acquired;
|
|
}
|
|
|
|
void
|
|
ipa_topo_release_startup_inprogress(void)
|
|
{
|
|
slapi_lock_mutex(topo_shared_conf.conf_lock);
|
|
topo_shared_conf.startup_inprogress = 0;
|
|
slapi_unlock_mutex(topo_shared_conf.conf_lock);
|
|
}
|
|
|
|
TopoReplicaHost *
|
|
ipa_topo_cfg_host_find(TopoReplica *tconf, char *findhost, int lock)
|
|
{
|
|
TopoReplicaHost *host = NULL;
|
|
|
|
if (tconf->hosts == NULL) return NULL;
|
|
|
|
if (lock) slapi_lock_mutex(tconf->repl_lock);
|
|
for (host=tconf->hosts;host;host=host->next) {
|
|
if (host->hostname == NULL) {
|
|
/* this check is done to avoid a crash,
|
|
* for which the root cause is not yet known.
|
|
* Avoid the crash and log an error
|
|
*/
|
|
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
|
"ipa_topo_cfg_host_find: found a NULL hostname in host list\n");
|
|
continue;
|
|
}
|
|
if (!strcasecmp(host->hostname,findhost)) {
|
|
break;
|
|
}
|
|
}
|
|
if (lock) slapi_unlock_mutex(tconf->repl_lock);
|
|
return host;
|
|
}
|
|
|
|
TopoReplicaHost *
|
|
ipa_topo_cfg_host_new(char *newhost)
|
|
{
|
|
TopoReplicaHost *newnode;
|
|
newnode = (TopoReplicaHost *)slapi_ch_malloc(sizeof(TopoReplicaHost));
|
|
newnode->next = NULL;
|
|
newnode->hostname = newhost;
|
|
return newnode;
|
|
}
|
|
|
|
void
|
|
ipa_topo_cfg_host_add(TopoReplica *replica, char *newhost)
|
|
{
|
|
TopoReplicaHost *hostnode = NULL;
|
|
if (replica == NULL || newhost == NULL) return;
|
|
|
|
slapi_lock_mutex(replica->repl_lock);
|
|
if (ipa_topo_cfg_host_find(replica, newhost, 0)) {
|
|
/* host already added */
|
|
slapi_unlock_mutex(replica->repl_lock);
|
|
return;
|
|
}
|
|
hostnode = ipa_topo_cfg_host_new(slapi_ch_strdup(newhost));
|
|
hostnode->next = replica->hosts;
|
|
replica->hosts = hostnode;
|
|
slapi_unlock_mutex(replica->repl_lock);
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
ipa_topo_cfg_host_free(TopoReplicaHost **node)
|
|
{
|
|
slapi_ch_free((void **)&((*node)->hostname));
|
|
slapi_ch_free((void **)node);
|
|
}
|
|
|
|
void
|
|
ipa_topo_cfg_host_del(Slapi_Entry *hostentry)
|
|
{
|
|
char *delhost;
|
|
TopoReplicaHost *hostnode = NULL;
|
|
TopoReplicaHost *prevnode = NULL;
|
|
char **repl_root = NULL;
|
|
TopoReplica *replica = NULL;
|
|
int i;
|
|
|
|
delhost = slapi_entry_attr_get_charptr(hostentry,"cn");
|
|
if (delhost == NULL) return;
|
|
|
|
repl_root = slapi_entry_attr_get_charray(hostentry,"ipaReplTopoManagedSuffix");
|
|
if (repl_root == NULL || *repl_root == NULL) return;
|
|
|
|
for (i=0; repl_root[i];i++) {
|
|
replica = ipa_topo_cfg_replica_find(repl_root[i], 1);
|
|
if (replica == NULL) continue;
|
|
|
|
slapi_lock_mutex(replica->repl_lock);
|
|
hostnode = replica->hosts;
|
|
prevnode = NULL;
|
|
while (hostnode) {
|
|
if (!strcasecmp(hostnode->hostname,delhost)) {
|
|
/*remove from list and free*/
|
|
if (prevnode) {
|
|
prevnode->next = hostnode->next;
|
|
} else {
|
|
replica->hosts = hostnode->next;
|
|
}
|
|
ipa_topo_cfg_host_free(&hostnode);
|
|
break;
|
|
} else {
|
|
prevnode = hostnode;
|
|
hostnode = hostnode->next;
|
|
}
|
|
}
|
|
slapi_unlock_mutex(replica->repl_lock);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
TopoReplicaSegment *
|
|
ipa_topo_cfg_replica_segment_find(TopoReplica *replica, char *leftHost, char *rightHost, int dir, int lock)
|
|
{
|
|
TopoReplicaSegment *tsegm = NULL;
|
|
TopoReplicaSegmentList *segments = NULL;
|
|
int reverse_dir = SEGMENT_BIDIRECTIONAL;
|
|
|
|
if (dir == SEGMENT_LEFT_RIGHT) reverse_dir = SEGMENT_RIGHT_LEFT;
|
|
else if (dir == SEGMENT_RIGHT_LEFT) reverse_dir = SEGMENT_LEFT_RIGHT;
|
|
else reverse_dir = SEGMENT_BIDIRECTIONAL;
|
|
|
|
if (lock) slapi_lock_mutex(replica->repl_lock);
|
|
segments = replica->repl_segments;
|
|
while (segments) {
|
|
|
|
tsegm = segments->segm;
|
|
if ( (!strcasecmp(leftHost,tsegm->from) && !strcasecmp(rightHost,tsegm->to) &&
|
|
(tsegm->direct & dir)) ||
|
|
(!strcasecmp(leftHost,tsegm->to) && !strcasecmp(rightHost,tsegm->from) &&
|
|
(tsegm->direct & reverse_dir))) {
|
|
break;
|
|
}
|
|
tsegm = NULL;
|
|
segments = segments->next;
|
|
}
|
|
if (lock) slapi_unlock_mutex(replica->repl_lock);
|
|
|
|
return tsegm;
|
|
}
|
|
|
|
TopoReplicaAgmt *
|
|
ipa_topo_cfg_agmt_dup(TopoReplicaAgmt *agmt)
|
|
{
|
|
TopoReplicaAgmt *dup = NULL;
|
|
|
|
if (agmt == NULL) return NULL;
|
|
|
|
dup = (TopoReplicaAgmt *) slapi_ch_calloc(1,sizeof(TopoReplicaAgmt));
|
|
dup->rdn = slapi_ch_strdup(agmt->rdn);
|
|
dup->origin = slapi_ch_strdup(agmt->origin);
|
|
dup->target = slapi_ch_strdup(agmt->target);
|
|
dup->enabled = slapi_ch_strdup(agmt->enabled);
|
|
dup->repl_root = slapi_ch_strdup(agmt->repl_root);
|
|
dup->strip_attrs = slapi_ch_strdup(agmt->strip_attrs);
|
|
dup->total_attrs = slapi_ch_strdup(agmt->total_attrs);
|
|
dup->repl_attrs = slapi_ch_strdup(agmt->repl_attrs);
|
|
dup->repl_pause = slapi_ch_strdup(agmt->repl_pause);
|
|
dup->repl_timeout = slapi_ch_strdup(agmt->repl_timeout);
|
|
dup->repl_refresh = slapi_ch_strdup(agmt->repl_refresh);
|
|
dup->repl_transport = slapi_ch_strdup(agmt->repl_transport);
|
|
dup->repl_bind_dn = slapi_ch_strdup(agmt->repl_bind_dn);
|
|
dup->repl_bind_cred = slapi_ch_strdup(agmt->repl_bind_cred);
|
|
dup->repl_bind_method = slapi_ch_strdup(agmt->repl_bind_method);
|
|
|
|
return dup;
|
|
}
|
|
|
|
TopoReplicaAgmt *
|
|
ipa_topo_cfg_agmt_dup_reverse(TopoReplicaAgmt *agmt)
|
|
{
|
|
char *tmp;
|
|
TopoReplicaAgmt *dup = NULL;
|
|
dup = ipa_topo_cfg_agmt_dup(agmt);
|
|
|
|
if (dup == NULL) return NULL;
|
|
|
|
tmp = dup->origin;
|
|
dup->origin = dup->target;
|
|
dup->target = tmp;
|
|
|
|
/* this is not enough, if a reverse agmt is
|
|
* created because segment becomes bidirectional
|
|
* we don't really know the rdn of the other direction
|
|
* As long as this info is not in the segment,
|
|
* assume std agmt naming and do best effort.
|
|
*/
|
|
|
|
slapi_ch_free_string(&dup->rdn);
|
|
dup->rdn = ipa_topo_agmt_std_rdn(dup->target);
|
|
return dup;
|
|
}
|
|
static void
|
|
ipa_topo_cfg_agmt_done(TopoReplicaAgmt *agmt)
|
|
{
|
|
if (agmt == NULL) return;
|
|
|
|
slapi_ch_free_string(&agmt->origin);
|
|
slapi_ch_free_string(&agmt->target);
|
|
slapi_ch_free_string(&agmt->enabled);
|
|
slapi_ch_free_string(&agmt->repl_root);
|
|
slapi_ch_free_string(&agmt->strip_attrs);
|
|
slapi_ch_free_string(&agmt->total_attrs);
|
|
slapi_ch_free_string(&agmt->repl_attrs);
|
|
slapi_ch_free_string(&agmt->repl_pause);
|
|
slapi_ch_free_string(&agmt->repl_timeout);
|
|
slapi_ch_free_string(&agmt->repl_refresh);
|
|
slapi_ch_free_string(&agmt->repl_transport);
|
|
slapi_ch_free_string(&agmt->repl_bind_dn);
|
|
slapi_ch_free_string(&agmt->repl_bind_cred);
|
|
slapi_ch_free_string(&agmt->repl_bind_method);
|
|
}
|
|
|
|
static void
|
|
ipa_topo_cfg_segment_done(TopoReplicaSegment *tsegm)
|
|
{
|
|
if (tsegm == NULL) return;
|
|
|
|
slapi_ch_free_string(&tsegm->name);
|
|
slapi_ch_free_string(&tsegm->from);
|
|
slapi_ch_free_string(&tsegm->to);
|
|
ipa_topo_cfg_agmt_done(tsegm->left);
|
|
ipa_topo_cfg_agmt_done(tsegm->right);
|
|
slapi_ch_free((void **)&tsegm->left);
|
|
slapi_ch_free((void **)&tsegm->right);
|
|
}
|
|
|
|
void
|
|
ipa_topo_cfg_segment_free(TopoReplicaSegment *tsegm)
|
|
{
|
|
ipa_topo_cfg_segment_done(tsegm);
|
|
slapi_ch_free((void **)&tsegm);
|
|
}
|
|
|
|
TopoReplicaSegment *
|
|
ipa_topo_cfg_segment_dup(TopoReplicaSegment *orig)
|
|
{
|
|
TopoReplicaSegment *dup = NULL;
|
|
|
|
if (orig == NULL) return NULL;
|
|
|
|
dup = (TopoReplicaSegment *) slapi_ch_calloc(1,sizeof(TopoReplicaSegment));
|
|
dup->name = slapi_ch_strdup(orig->name);
|
|
dup->from = slapi_ch_strdup(orig->from);
|
|
dup->to = slapi_ch_strdup(orig->to);
|
|
dup->left = ipa_topo_cfg_agmt_dup(orig->left);
|
|
dup->left = ipa_topo_cfg_agmt_dup(orig->left);
|
|
dup->direct = orig->direct;
|
|
dup->state = orig->state;
|
|
return dup;
|
|
}
|
|
|
|
TopoReplicaSegment *
|
|
ipa_topo_cfg_segment_find(char *repl_root, char *leftHost, char *rightHost, int dir)
|
|
{
|
|
TopoReplicaSegment *tsegm = NULL;
|
|
TopoReplica *replica = NULL;
|
|
|
|
slapi_lock_mutex(topo_shared_conf.conf_lock);
|
|
|
|
replica = ipa_topo_cfg_replica_find(repl_root, 0);
|
|
if (replica) {
|
|
tsegm = ipa_topo_cfg_replica_segment_find(replica,leftHost,rightHost, dir, 1);
|
|
}
|
|
slapi_unlock_mutex(topo_shared_conf.conf_lock);
|
|
return tsegm;
|
|
}
|
|
|
|
void
|
|
ipa_topo_cfg_segment_set_visited(TopoReplica *replica, TopoReplicaSegment *vsegm)
|
|
{
|
|
TopoReplicaSegmentList *segments = NULL;
|
|
TopoReplicaSegment *tsegm = NULL;
|
|
char *leftHost = vsegm->from;
|
|
char *rightHost = vsegm->to;
|
|
|
|
slapi_lock_mutex(replica->repl_lock);
|
|
segments = replica->repl_segments;
|
|
while (segments) {
|
|
tsegm = segments->segm;
|
|
if ( (!strcasecmp(leftHost,tsegm->from) && !strcasecmp(rightHost,tsegm->to) &&
|
|
(tsegm->direct == SEGMENT_BIDIRECTIONAL || tsegm->direct == SEGMENT_LEFT_RIGHT)) ||
|
|
(!strcasecmp(leftHost,tsegm->to) && !strcasecmp(rightHost,tsegm->from) &&
|
|
(tsegm->direct == SEGMENT_BIDIRECTIONAL || tsegm->direct == SEGMENT_RIGHT_LEFT))) {
|
|
segments->visited = 1;
|
|
break;
|
|
}
|
|
tsegm = NULL;
|
|
segments = segments->next;
|
|
}
|
|
slapi_unlock_mutex(replica->repl_lock);
|
|
|
|
}
|
|
|
|
void
|
|
ipa_topo_cfg_segment_add(TopoReplica *replica, TopoReplicaSegment *tsegm)
|
|
{
|
|
TopoReplicaSegmentList *seglist = NULL;
|
|
|
|
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
|
"ipa_topo_cfg_segment_add: %s\n", tsegm->name);
|
|
slapi_lock_mutex(replica->repl_lock);
|
|
if (ipa_topo_cfg_replica_segment_find(replica,
|
|
tsegm->from,
|
|
tsegm->to, tsegm->direct, 0)){
|
|
/* already exists: log error */
|
|
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
|
"ipa_topo_cfg_segment_add: error: segment exists: %s\n",
|
|
tsegm->name);
|
|
goto done;
|
|
}
|
|
seglist = (TopoReplicaSegmentList *)
|
|
slapi_ch_calloc(1,sizeof(TopoReplicaSegmentList));
|
|
seglist->visited = 0;
|
|
seglist->segm = tsegm;
|
|
if (replica->repl_segments == NULL) {
|
|
replica->repl_segments = seglist;
|
|
} else {
|
|
seglist->next = replica->repl_segments;
|
|
replica->repl_segments = seglist;
|
|
}
|
|
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
|
"ipa_topo_cfg_segment_added: %s\n", tsegm->name);
|
|
done:
|
|
slapi_unlock_mutex(replica->repl_lock);
|
|
}
|
|
|
|
void
|
|
ipa_topo_cfg_segment_del(TopoReplica *tconf, TopoReplicaSegment *tsegm)
|
|
{
|
|
TopoReplicaSegmentList *segment = NULL;
|
|
TopoReplicaSegmentList *prev = NULL;
|
|
|
|
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
|
"ipa_topo_cfg_segment_del: %s\n", tsegm->name);
|
|
slapi_lock_mutex(tconf->repl_lock);
|
|
segment = tconf->repl_segments;
|
|
while (segment) {
|
|
if (segment->segm == tsegm) {
|
|
if (prev == NULL) {
|
|
tconf->repl_segments = segment->next;
|
|
} else {
|
|
prev->next = segment->next;
|
|
}
|
|
/* free segment */
|
|
ipa_topo_cfg_segment_free(tsegm);
|
|
slapi_ch_free((void **)&segment);
|
|
break;
|
|
}
|
|
prev = segment;
|
|
segment = segment->next;
|
|
}
|
|
slapi_unlock_mutex(tconf->repl_lock);
|
|
}
|
|
|
|
TopoReplica *
|
|
ipa_topo_cfg_replica_new(void)
|
|
{
|
|
TopoReplica *topoRepl;
|
|
topoRepl = (TopoReplica *)slapi_ch_malloc(sizeof(TopoReplica));
|
|
if (topoRepl) {
|
|
topoRepl->next = NULL;
|
|
topoRepl->repl_segments = NULL;
|
|
topoRepl->repl_root = NULL;
|
|
topoRepl->strip_attrs = NULL;
|
|
topoRepl->total_attrs = NULL;
|
|
topoRepl->repl_attrs = NULL;
|
|
topoRepl->shared_config_base = NULL;
|
|
topoRepl->hosts = NULL;
|
|
topoRepl->repl_lock = slapi_new_mutex();
|
|
}
|
|
return topoRepl;
|
|
|
|
}
|
|
|
|
int
|
|
ipa_topo_cfg_replica_add(TopoReplica *tconf)
|
|
{
|
|
int rc = 0;
|
|
slapi_lock_mutex(topo_shared_conf.conf_lock);
|
|
if (topo_shared_conf.replicas == NULL) {
|
|
topo_shared_conf.replicas = tconf;
|
|
} else if (ipa_topo_cfg_replica_find(tconf->repl_root,0)) {
|
|
/* log error: already exists */
|
|
rc = -1;
|
|
} else {
|
|
tconf->next = topo_shared_conf.replicas;
|
|
topo_shared_conf.replicas = tconf;
|
|
}
|
|
slapi_unlock_mutex(topo_shared_conf.conf_lock);
|
|
|
|
return rc;
|
|
}
|
|
|
|
void
|
|
ipa_topo_cfg_replica_del(TopoReplica *tconf)
|
|
{
|
|
/* TBD */
|
|
}
|
|
|
|
void
|
|
ipa_topo_cfg_replica_free(TopoReplica *tconf)
|
|
{
|
|
TopoReplicaSegmentList *seg, *seg_next;
|
|
TopoReplicaHost *host, *host_next;
|
|
if (tconf) {
|
|
slapi_destroy_mutex(tconf->repl_lock);
|
|
slapi_ch_free_string(&tconf->shared_config_base);
|
|
slapi_ch_free_string(&tconf->repl_root);
|
|
seg = tconf->repl_segments;
|
|
while (seg) {
|
|
seg_next = seg->next;
|
|
ipa_topo_cfg_segment_free(seg->segm);
|
|
slapi_ch_free((void **)&seg);
|
|
seg = seg_next;
|
|
}
|
|
host = tconf->hosts;
|
|
while (host) {
|
|
host_next = host->next;
|
|
slapi_ch_free_string(&host->hostname);
|
|
slapi_ch_free((void **)&host);
|
|
host = host_next;
|
|
}
|
|
slapi_ch_free((void **)&tconf);
|
|
}
|
|
|
|
}
|
|
|
|
TopoReplica *
|
|
ipa_topo_cfg_replica_find(char *repl_root, int lock)
|
|
{
|
|
TopoReplica *tconf = NULL;
|
|
|
|
if (lock) {
|
|
slapi_lock_mutex(topo_shared_conf.conf_lock);
|
|
}
|
|
if (topo_shared_conf.replicas == NULL) goto done;
|
|
|
|
tconf = topo_shared_conf.replicas;
|
|
while (tconf) {
|
|
if (!strcasecmp(repl_root,tconf->repl_root)) {
|
|
break;
|
|
}
|
|
tconf = tconf->next;
|
|
}
|
|
|
|
done:
|
|
if (lock) {
|
|
slapi_unlock_mutex(topo_shared_conf.conf_lock);
|
|
}
|
|
return tconf;
|
|
}
|