summaryrefslogtreecommitdiffstats
path: root/daemons/ipa-slapi-plugins/dna/dna.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemons/ipa-slapi-plugins/dna/dna.c')
-rw-r--r--daemons/ipa-slapi-plugins/dna/dna.c1462
1 files changed, 0 insertions, 1462 deletions
diff --git a/daemons/ipa-slapi-plugins/dna/dna.c b/daemons/ipa-slapi-plugins/dna/dna.c
deleted file mode 100644
index cb6a0629c..000000000
--- a/daemons/ipa-slapi-plugins/dna/dna.c
+++ /dev/null
@@ -1,1462 +0,0 @@
-/** BEGIN COPYRIGHT BLOCK
- * This Program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation; version 2 of the License.
- *
- * This Program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * In addition, as a special exception, Red Hat, Inc. gives You the additional
- * right to link the code of this Program with code not covered under the GNU
- * General Public License ("Non-GPL Code") and to distribute linked combinations
- * including the two, subject to the limitations in this paragraph. Non-GPL Code
- * permitted under this exception must only link to the code of this Program
- * through those well defined interfaces identified in the file named EXCEPTION
- * found in the source code files (the "Approved Interfaces"). The files of
- * Non-GPL Code may instantiate templates or use macros or inline functions from
- * the Approved Interfaces without causing the resulting work to be covered by
- * the GNU General Public License. Only Red Hat, Inc. may make changes or
- * additions to the list of Approved Interfaces. You must obey the GNU General
- * Public License in all respects for all of the Program code and other code used
- * in conjunction with the Program except the Non-GPL Code covered by this
- * exception. If you modify this file, you may extend this exception to your
- * version of the file, but you are not obligated to do so. If you do not wish to
- * provide this exception without modification, you must delete this exception
- * statement from your version and license this file solely under the GPL without
- * exception.
- *
- *
- * Author: Pete Rowley
- *
- * Copyright (C) 2007 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-
-/**
- * Distributed Numeric Assignment plug-in
- */
-
-#include <dirsrv/slapi-plugin.h>
-
-#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-#include <errno.h>
-/*#include "portable.h"*/
-#include "nspr.h"
-/*#include "slapi-private.h"*/
-/*#include "dirlite_strings.h"*/
-/*#include "dirver.h"*/
-
-#include "prclist.h"
-#include "ldif.h"
-
-/* get file mode flags for unix */
-#ifndef _WIN32
-#include <sys/stat.h>
-#endif
-
-#define DNA_PLUGIN_SUBSYSTEM "ipa-dna-plugin"
-#define DNA_PLUGIN_VERSION 0x00020000
-
-/* temporary */
-#define DNA_DN "cn=ipa-dna,cn=plugins,cn=config"
-
-#define DNA_SUCCESS 0
-#define DNA_FAILURE -1
-
-/**
- * DNA config types
- */
-#define DNA_TYPE "dnaType"
-#define DNA_PREFIX "dnaPrefix"
-#define DNA_NEXTVAL "dnaNextValue"
-#define DNA_INTERVAL "dnaInterval"
-#define DNA_GENERATE "dnaMagicRegen"
-#define DNA_FILTER "dnaFilter"
-#define DNA_SCOPE "dnaScope"
-
-/* since v2 */
-#define DNA_MAXVAL "dnaMaxValue"
-#define DNA_SHARED_CFG_DN "dnaSharedCfgDN"
-
-/* Shared Config */
-#define DNA_GLOBAL_RANGE "dnaGlobalRange"
-#define DNA_RANGE "dnaRange"
-#define DNA_MAX_RANGE_SIZE "dnaMaxRangeSize"
-#define DNA_CHUNK_SIZE "dnaChunkSize"
-
-
-
-#define FEATURE_DESC "IPA Distributed Numeric Assignment"
-#define PLUGIN_DESC "IPA Distributed Numeric Assignment plugin"
-#define PLUGIN_DESC_INT_PREOP PLUGIN_DESC " preop internal"
-#define PLUGIN_DESC_POSTOP PLUGIN_DESC " postop"
-#define PLUGIN_DESC_INT_POSTOP PLUGIN_DESC " postop internal"
-
-static Slapi_PluginDesc pdesc = { FEATURE_DESC,
- "FreeIPA project", "FreeIPA/1.0",
- PLUGIN_DESC
-};
-
-
-/**
- * linked list of config entries
- */
-
-struct configEntry {
- PRCList list;
- char *dn;
- char *type;
- char *prefix;
- PRUint64 nextval;
- PRUint64 interval;
- PRUint64 maxval;
- char *filter;
- struct slapi_filter *slapi_filter;
- char *generate;
- char *scope;
-};
-
-static PRCList *dna_global_config = NULL;
-static PRRWLock *g_dna_cache_lock;
-
-static void *_PluginID = NULL;
-static char *_PluginDN = NULL;
-
-static int g_plugin_started = 0;
-
-
-/*
- * new value lock
- */
-static Slapi_Mutex *g_new_value_lock;
-
-/**
- *
- * DNA plug-in management functions
- *
- */
-int ipa_dna_init(Slapi_PBlock * pb);
-static int dna_start(Slapi_PBlock * pb);
-static int dna_close(Slapi_PBlock * pb);
-static int dna_internal_preop_init(Slapi_PBlock *pb);
-static int dna_postop_init(Slapi_PBlock * pb);
-
-/**
- *
- * Local operation functions
- *
- */
-static int loadPluginConfig();
-static int parseConfigEntry(Slapi_Entry * e);
-static void deleteConfig();
-static void freeConfigEntry(struct configEntry ** entry);
-
-/**
- *
- * helpers
- *
- */
-static char *dna_get_dn(Slapi_PBlock * pb);
-static int dna_dn_is_config(char *dn);
-static int dna_get_next_value(struct configEntry * config_entry,
- char **next_value_ret);
-
-/**
- *
- * the ops (where the real work is done)
- *
- */
-static int dna_config_check_post_op(Slapi_PBlock * pb);
-static int dna_pre_op(Slapi_PBlock * pb, int modtype);
-static int dna_mod_pre_op(Slapi_PBlock * pb);
-static int dna_add_pre_op(Slapi_PBlock * pb);
-
-/**
- * debug functions - global, for the debugger
- */
-void dnaDumpConfig();
-void dnaDumpConfigEntry(struct configEntry *);
-
-/**
- * set the debug level
- */
-#ifdef _WIN32
-int *module_ldap_debug = 0;
-
-void plugin_init_debug_level(int *level_ptr)
-{
- module_ldap_debug = level_ptr;
-}
-#endif
-
-/**
- *
- * Deal with cache locking
- *
- */
-void dna_read_lock()
-{
- PR_RWLock_Rlock(g_dna_cache_lock);
-}
-
-void dna_write_lock()
-{
- PR_RWLock_Wlock(g_dna_cache_lock);
-}
-
-void dna_unlock()
-{
- PR_RWLock_Unlock(g_dna_cache_lock);
-}
-
-/**
- *
- * Get the dna plug-in version
- *
- */
-int dna_version()
-{
- return DNA_PLUGIN_VERSION;
-}
-
-/**
- * Plugin identity mgmt
- */
-void setPluginID(void *pluginID)
-{
- _PluginID = pluginID;
-}
-
-void *getPluginID()
-{
- return _PluginID;
-}
-
-void setPluginDN(char *pluginDN)
-{
- _PluginDN = pluginDN;
-}
-
-char *getPluginDN()
-{
- return _PluginDN;
-}
-
-/*
- dna_init
- -------------
- adds our callbacks to the list
-*/
-int ipa_dna_init(Slapi_PBlock * pb)
-{
- int status = DNA_SUCCESS;
- char *plugin_identity = NULL;
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "--> ipa_dna_init\n");
-
- /**
- * Store the plugin identity for later use.
- * Used for internal operations
- */
-
- slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &plugin_identity);
- PR_ASSERT(plugin_identity);
- setPluginID(plugin_identity);
-
- if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION,
- SLAPI_PLUGIN_VERSION_01) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN,
- (void *) dna_start) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN,
- (void *) dna_close) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION,
- (void *) &pdesc) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_MODIFY_FN,
- (void *) dna_mod_pre_op) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_ADD_FN,
- (void *) dna_add_pre_op) != 0 ||
- /* internal preoperation */
- slapi_register_plugin("internalpreoperation", /* op type */
- 1, /* Enabled */
- "dna_internal_preop_init", /* this function desc */
- dna_internal_preop_init, /* init func */
- PLUGIN_DESC_INT_PREOP, /* plugin desc */
- NULL, /* ? */
- plugin_identity /* access control */
- ) ||
- /* the config change checking post op */
- slapi_register_plugin("postoperation", /* op type */
- 1, /* Enabled */
- "dna_postop_init", /* this function desc */
- dna_postop_init, /* init func for post op */
- PLUGIN_DESC_POSTOP, /* plugin desc */
- NULL, /* ? */
- plugin_identity /* access control */
- )
- ) {
- slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
- "ipa_dna_init: failed to register plugin\n");
- status = DNA_FAILURE;
- }
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "<-- ipa_dna_init\n");
- return status;
-}
-
-
-static int
-dna_internal_preop_init(Slapi_PBlock *pb)
-{
- int status = DNA_SUCCESS;
-
- if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION,
- SLAPI_PLUGIN_VERSION_01) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION,
- (void *) &pdesc) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_PRE_MODIFY_FN,
- (void *) dna_mod_pre_op) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_PRE_ADD_FN,
- (void *) dna_add_pre_op) != 0) {
- status = DNA_FAILURE;
- }
-
- return status;
-}
-
-
-static int dna_postop_init(Slapi_PBlock * pb)
-{
- int status = DNA_SUCCESS;
-
- if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION,
- SLAPI_PLUGIN_VERSION_01) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION,
- (void *) &pdesc) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_POST_ADD_FN,
- (void *) dna_config_check_post_op) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODRDN_FN,
- (void *) dna_config_check_post_op) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_POST_DELETE_FN,
- (void *) dna_config_check_post_op) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODIFY_FN,
- (void *) dna_config_check_post_op) != 0) {
- slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
- "dna_postop_init: failed to register plugin\n");
- status = DNA_FAILURE;
- }
-
- return status;
-}
-
-/*
- dna_start
- --------------
- Kicks off the config cache.
- It is called after dna_init.
-*/
-static int dna_start(Slapi_PBlock * pb)
-{
- char *plugindn = NULL;
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "--> dna_start\n");
-
- /* Check if we're already started */
- if (g_plugin_started) {
- goto done;
- }
-
- g_dna_cache_lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, "dna");
- g_new_value_lock = slapi_new_mutex();
-
- if (!g_dna_cache_lock || !g_new_value_lock) {
- slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
- "dna_start: lock creation failed\n");
-
- return DNA_FAILURE;
- }
-
- /**
- * Get the plug-in target dn from the system
- * and store it for future use. This should avoid
- * hardcoding of DN's in the code.
- */
- slapi_pblock_get(pb, SLAPI_TARGET_DN, &plugindn);
- if (NULL == plugindn || 0 == strlen(plugindn)) {
- slapi_log_error(SLAPI_LOG_PLUGIN, DNA_PLUGIN_SUBSYSTEM,
- "dna_start: had to use hard coded config dn\n");
- plugindn = DNA_DN;
- } else {
- slapi_log_error(SLAPI_LOG_PLUGIN, DNA_PLUGIN_SUBSYSTEM,
- "dna_start: config at %s\n", plugindn);
-
- }
-
- setPluginDN(plugindn);
-
- /**
- * Load the config for our plug-in
- */
- dna_global_config = (PRCList *)
- slapi_ch_calloc(1, sizeof(struct configEntry));
- PR_INIT_CLIST(dna_global_config);
-
- if (loadPluginConfig() != DNA_SUCCESS) {
- slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
- "dna_start: unable to load plug-in configuration\n");
- return DNA_FAILURE;
- }
-
- g_plugin_started = 1;
- slapi_log_error(SLAPI_LOG_PLUGIN, DNA_PLUGIN_SUBSYSTEM,
- "dna: ready for service\n");
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "<-- dna_start\n");
-
-done:
- return DNA_SUCCESS;
-}
-
-/*
- dna_close
- --------------
- closes down the cache
-*/
-static int dna_close(Slapi_PBlock * pb)
-{
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "--> dna_close\n");
-
- deleteConfig();
-
- slapi_ch_free((void **)&dna_global_config);
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "<-- dna_close\n");
-
- return DNA_SUCCESS;
-}
-
-/*
- * config looks like this
- * - cn=myplugin
- * --- cn=posix
- * ------ cn=accounts
- * ------ cn=groups
- * --- cn=samba
- * --- cn=etc
- * ------ cn=etc etc
- */
-static int loadPluginConfig()
-{
- int status = DNA_SUCCESS;
- int result;
- int i;
- Slapi_PBlock *search_pb;
- Slapi_Entry **entries = NULL;
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "--> loadPluginConfig\n");
-
- dna_write_lock();
- deleteConfig();
-
- search_pb = slapi_pblock_new();
-
- slapi_search_internal_set_pb(search_pb, getPluginDN(),
- LDAP_SCOPE_SUBTREE, "objectclass=*",
- NULL, 0, NULL, NULL, getPluginID(), 0);
- slapi_search_internal_pb(search_pb);
- slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
-
- if (LDAP_SUCCESS != result) {
- status = DNA_FAILURE;
- goto cleanup;
- }
-
- slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
- &entries);
- if (NULL == entries || NULL == entries[0]) {
- status = DNA_SUCCESS;
- goto cleanup;
- }
-
- for (i = 0; (entries[i] != NULL); i++) {
- status = parseConfigEntry(entries[i]);
- if (DNA_SUCCESS != status)
- break;
- }
-
- cleanup:
- slapi_free_search_results_internal(search_pb);
- slapi_pblock_destroy(search_pb);
- dna_unlock();
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "<-- loadPluginConfig\n");
-
- return status;
-}
-
-static int parseConfigEntry(Slapi_Entry * e)
-{
- char *value;
- struct configEntry *entry;
- struct configEntry *config_entry;
- PRCList *list;
- int entry_added = 0;
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "--> parseConfigEntry\n");
-
- entry = (struct configEntry *)
- slapi_ch_calloc(1, sizeof(struct configEntry));
- if (NULL == entry)
- goto bail;
-
- value = slapi_entry_get_ndn(e);
- if (value) {
- entry->dn = strdup(value);
- }
-
- slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
- "----------> dn [%s]\n", entry->dn, 0, 0);
-
- value = slapi_entry_attr_get_charptr(e, DNA_TYPE);
- if (value) {
- entry->type = value;
- } else
- goto bail;
-
- slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
- "----------> dnaType [%s]\n", entry->type, 0, 0);
-
- /* FIXME: check the attribute type, it must suport matching rules and be
- * indexed, these are requirements and failure to meet them should result in
- * the configuration to be disarded and an ERROR logged prominently */
-
- value = slapi_entry_attr_get_charptr(e, DNA_NEXTVAL);
- if (value) {
- entry->nextval = strtoul(value, 0, 0);
- slapi_ch_free_string(&value);
- } else
- goto bail;
-
- slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
- "----------> dnaNextValue [%d]\n", entry->nextval, 0,
- 0);
-
- value = slapi_entry_attr_get_charptr(e, DNA_PREFIX);
- if (value && value[0]) {
- entry->prefix = value;
- }
-
- slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
- "----------> dnaPrefix [%s]\n", entry->prefix, 0, 0);
-
- value = slapi_entry_attr_get_charptr(e, DNA_INTERVAL);
- if (value) {
- entry->interval = strtoul(value, 0, 0);
- } else
- goto bail;
-
- slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
- "----------> dnaInterval [%s]\n", value, 0, 0);
-
- slapi_ch_free_string(&value);
-
- value = slapi_entry_attr_get_charptr(e, DNA_GENERATE);
- if (value) {
- entry->generate = value;
- }
-
- slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
- "----------> dnaMagicRegen [%s]\n", entry->generate,
- 0, 0);
-
- value = slapi_entry_attr_get_charptr(e, DNA_FILTER);
- if (value) {
- entry->filter = value;
- entry->slapi_filter = slapi_str2filter(value);
- } else
- goto bail;
-
- slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
- "----------> dnaFilter [%s]\n", value, 0, 0);
-
- value = slapi_entry_attr_get_charptr(e, DNA_SCOPE);
- if (value) {
- entry->scope = slapi_dn_normalize(value);
- }
-
- slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
- "----------> dnaScope [%s]\n", entry->scope, 0, 0);
-
- /* optional, if not specified set -1 which is converted to the max unisgnee
- * value */
- value = slapi_entry_attr_get_charptr(e, DNA_MAXVAL);
- if (value) {
- entry->maxval = strtoul(value, 0, 0);
-
- slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
- "----------> dnaMaxValue [%ld]\n", value, 0, 0);
-
- slapi_ch_free_string(&value);
- } else
- entry->maxval = -1;
-
-
- /**
- * Finally add the entry to the list
- * we group by type then by filter
- * and finally sort by dn length with longer dn's
- * first - this allows the scope checking
- * code to be simple and quick and
- * cunningly linear
- */
- if (!PR_CLIST_IS_EMPTY(dna_global_config)) {
- list = PR_LIST_HEAD(dna_global_config);
- while (list != dna_global_config) {
- config_entry = (struct configEntry *) list;
-
- if (slapi_attr_type_cmp(config_entry->type, entry->type, 1))
- goto next;
-
- if (slapi_filter_compare(config_entry->slapi_filter,
- entry->slapi_filter))
- goto next;
-
- if (slapi_dn_issuffix(entry->scope, config_entry->scope)) {
- PR_INSERT_BEFORE(&(entry->list), list);
- slapi_log_error(SLAPI_LOG_CONFIG,
- DNA_PLUGIN_SUBSYSTEM,
- "store [%s] before [%s] \n", entry->scope,
- config_entry->scope, 0);
- entry_added = 1;
- break;
- }
-
- next:
- list = PR_NEXT_LINK(list);
-
- if (dna_global_config == list) {
- /* add to tail */
- PR_INSERT_BEFORE(&(entry->list), list);
- slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
- "store [%s] at tail\n", entry->scope, 0,
- 0);
- entry_added = 1;
- break;
- }
- }
- } else {
- /* first entry */
- PR_INSERT_LINK(&(entry->list), dna_global_config);
- slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
- "store [%s] at head \n", entry->scope, 0, 0);
- entry_added = 1;
- }
-
- bail:
- if (0 == entry_added) {
- slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
- "config entry [%s] skipped\n", entry->dn, 0, 0);
- freeConfigEntry(&entry);
- }
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "<-- parseConfigEntry\n");
-
- return DNA_SUCCESS;
-}
-
-static void freeConfigEntry(struct configEntry ** entry)
-{
- struct configEntry *e = *entry;
-
- if (e->dn) {
- slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
- "freeing config entry [%s]\n", e->dn, 0, 0);
- slapi_ch_free_string(&e->dn);
- }
-
- if (e->type)
- slapi_ch_free_string(&e->type);
-
- if (e->prefix)
- slapi_ch_free_string(&e->prefix);
-
- if (e->filter)
- slapi_ch_free_string(&e->filter);
-
- if (e->slapi_filter)
- slapi_filter_free(e->slapi_filter, 1);
-
- if (e->generate)
- slapi_ch_free_string(&e->generate);
-
- if (e->scope)
- slapi_ch_free_string(&e->scope);
-
- slapi_ch_free((void **) entry);
-}
-
-static void deleteConfigEntry(PRCList * entry)
-{
- PR_REMOVE_LINK(entry);
- freeConfigEntry((struct configEntry **) & entry);
-}
-
-static void deleteConfig()
-{
- PRCList *list;
-
- while (!PR_CLIST_IS_EMPTY(dna_global_config)) {
- list = PR_LIST_HEAD(dna_global_config);
- deleteConfigEntry(list);
- }
-
- return;
-}
-
-/****************************************************
- Distributed ranges Helpers
-****************************************************/
-
-static int dna_fix_maxval(Slapi_DN *dn, PRUint64 *cur, PRUint64 *max)
-{
- /* TODO: check the main partition to see if another range
- * is available, and set the new local configuration
- * accordingly.
- * If a new range is not available run the retrieval task
- * and simply return error
- */
-
- return LDAP_OPERATIONS_ERROR;
-}
-
-static void dna_notice_allocation(Slapi_DN *dn, PRUint64 new)
-{
- /* TODO: check if we passed a new chunk threshold and update
- * the shared configuration on the public partition.
- */
-
- return;
-}
-
-/****************************************************
- Helpers
-****************************************************/
-
-static char *dna_get_dn(Slapi_PBlock * pb)
-{
- char *dn = 0;
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "--> dna_get_dn\n");
-
- if (slapi_pblock_get(pb, SLAPI_TARGET_DN, &dn)) {
- slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
- "dna_get_dn: failed to get dn of changed entry");
- goto bail;
- }
-
-/* slapi_dn_normalize( dn );
-*/
- bail:
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "<-- dna_get_dn\n");
-
- return dn;
-}
-
-/* config check
- matching config dn or a descendent reloads config
-*/
-static int dna_dn_is_config(char *dn)
-{
- int ret = 0;
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "--> dna_is_config\n");
-
- if (slapi_dn_issuffix(dn, getPluginDN())) {
- ret = 1;
- }
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "<-- dna_is_config\n");
-
- return ret;
-}
-
-#define DNA_LDAP_TAG_SK_REVERSE 0x81L
-
-static LDAPControl *dna_build_sort_control(const char *attr)
-{
- LDAPControl *ctrl;
- BerElement *ber;
- int rc;
-
- ber = ber_alloc();
- if (NULL == ber)
- return NULL;
-
- rc = ber_printf(ber, "{{stb}}", attr, DNA_LDAP_TAG_SK_REVERSE, 1);
- if (-1 == rc) {
- ber_free(ber, 1);
- return NULL;
- }
-
- rc = slapi_build_control(LDAP_CONTROL_SORTREQUEST, ber, 1, &ctrl);
-
- ber_free(ber, 1);
-
- if (LDAP_SUCCESS != rc)
- return NULL;
-
- return ctrl;
-}
-
-/****************************************************
- Functions that actually do things other
- than config and startup
-****************************************************/
-
-/* we do search all values between newval and maxval asking the
- * server to sort them, then we check the first free spot and
- * use it as newval */
-static int dna_first_free_value(struct configEntry *config_entry,
- PRUint64 *newval,
- PRUint64 maxval,
- PRUint64 increment)
-{
- Slapi_Entry **entries = NULL;
- Slapi_PBlock *pb = NULL;
- LDAPControl **ctrls;
- char *attrs[2];
- char *filter;
- char *prefix;
- char *type;
- int preflen;
- int result, status;
- PRUint64 tmpval, sval, i;
- char *strval = NULL;
-
- prefix = config_entry->prefix;
- type = config_entry->type;
- tmpval = *newval;
-
- attrs[0] = type;
- attrs[1] = NULL;
-
- ctrls = (LDAPControl **)slapi_ch_calloc(2, sizeof(LDAPControl));
- if (NULL == ctrls)
- return LDAP_OPERATIONS_ERROR;
-
- ctrls[0] = dna_build_sort_control(config_entry->type);
- if (NULL == ctrls[0]) {
- slapi_ch_free((void **)&ctrls);
- return LDAP_OPERATIONS_ERROR;
- }
-
- filter = slapi_ch_smprintf("(&%s(&(%s>=%s%llu)(%s<=%s%llu)))",
- config_entry->filter,
- type, prefix?prefix:"", tmpval,
- type, prefix?prefix:"", maxval);
- if (NULL == filter) {
- ldap_control_free(ctrls[0]);
- slapi_ch_free((void **)&ctrls);
- return LDAP_OPERATIONS_ERROR;
- }
-
- pb = slapi_pblock_new();
- if (NULL == pb) {
- ldap_control_free(ctrls[0]);
- slapi_ch_free((void **)&ctrls);
- slapi_ch_free_string(&filter);
- return LDAP_OPERATIONS_ERROR;
- }
-
- slapi_search_internal_set_pb(pb, config_entry->scope,
- LDAP_SCOPE_SUBTREE, filter,
- attrs, 0, ctrls,
- NULL, getPluginID(), 0);
- slapi_search_internal_pb(pb);
-/*
- ldap_control_free(ctrls[0]);
-*/
- slapi_ch_free_string(&filter);
-
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
- if (LDAP_SUCCESS != result) {
- status = LDAP_OPERATIONS_ERROR;
- goto cleanup;
- }
-
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
- &entries);
-
- if (NULL == entries || NULL == entries[0]) {
- /* no values means we already have a good value */
- status = LDAP_SUCCESS;
- goto cleanup;
- }
-
- /* entries are sorted and filtered for value >= tval therefore if the
- * first one does not match tval it means that the value is free,
- * otherwise we need to cycle through values until we find a mismatch,
- * the first mismatch is the first free pit */
-
- preflen = prefix?strlen(prefix):0;
- sval = 0;
- for (i = 0; NULL != entries[i]; i++) {
- strval = slapi_entry_attr_get_charptr(entries[i], type);
- if (preflen) {
- if (strlen(strval) <= preflen) {
- /* something very wrong here ... */
- status = LDAP_OPERATIONS_ERROR;
- goto cleanup;
- }
- strval = &strval[preflen-1];
- }
-
- errno = 0;
- sval = strtoul(strval, 0, 0);
- if (errno) {
- /* something very wrong here ... */
- status = LDAP_OPERATIONS_ERROR;
- goto cleanup;
- }
- slapi_ch_free_string(&strval);
-
- if (tmpval != sval)
- break;
-
- if (maxval < sval)
- break;
-
- tmpval += increment;
- }
-
- *newval = tmpval;
- status = LDAP_SUCCESS;
-
-cleanup:
- slapi_ch_free_string(&strval);
- slapi_free_search_results_internal(pb);
- slapi_pblock_destroy(pb);
-
- return status;
-}
-
-/*
- * Perform ldap operationally atomic increment
- * Return the next value to be assigned
- * Method:
- * 1. retrieve entry
- * 2. do increment operations
- * 3. remove current value, add new value in one operation
- * 4. if failed, and less than 3 times, goto 1
- */
-static int dna_get_next_value(struct configEntry *config_entry,
- char **next_value_ret)
-{
- Slapi_PBlock *pb = NULL;
- char *old_value = NULL;
- Slapi_Entry *e = NULL;
- Slapi_DN *dn = NULL;
- char *attrlist[4];
- int attempts;
- int ret;
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "--> dna_get_next_value\n");
-
- /* get pre-requisites to search */
- dn = slapi_sdn_new_dn_byref(config_entry->dn);
- attrlist[0] = DNA_NEXTVAL;
- attrlist[1] = DNA_MAXVAL;
- attrlist[2] = DNA_INTERVAL;
- attrlist[3] = NULL;
-
-
- /* the operation is constructed such that race conditions
- * to increment the value are detected and avoided - one wins,
- * one loses - however, there is no need for the server to compete
- * with itself so we lock here
- */
-
- slapi_lock_mutex(g_new_value_lock);
-
- for (attempts = 0; attempts < 3; attempts++) {
-
- LDAPMod mod_add;
- LDAPMod mod_delete;
- LDAPMod *mods[3];
- char *delete_val[2];
- char *add_val[2];
- char new_value[16];
- char *interval;
- char *max_value;
- PRUint64 increment = 1; /* default increment */
- PRUint64 setval = 0;
- PRUint64 newval = 0;
- PRUint64 maxval = -1;
-
- /* do update */
- ret = slapi_search_internal_get_entry(dn, attrlist, &e,
- getPluginID());
- if (LDAP_SUCCESS != ret) {
- ret = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- old_value = slapi_entry_attr_get_charptr(e, DNA_NEXTVAL);
- if (NULL == old_value) {
- ret = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- setval = strtoul(old_value, 0, 0);
-
- max_value = slapi_entry_attr_get_charptr(e, DNA_MAXVAL);
- if (max_value) {
- maxval = strtoul(max_value, 0, 0);
- slapi_ch_free_string(&max_value);
- }
-
- /* if not present the default is 1 */
- interval = slapi_entry_attr_get_charptr(e, DNA_INTERVAL);
- if (NULL != interval) {
- increment = strtoul(interval, 0, 0);
- }
-
- slapi_entry_free(e);
- e = NULL;
-
- /* check the value is actually in range */
-
- /* verify the new value is actually free and get the first
- * one free if not*/
- ret = dna_first_free_value(config_entry, &setval, maxval, increment);
- if (LDAP_SUCCESS != ret)
- goto done;
-
- /* try for a new range or fail */
- if (setval > maxval) {
- ret = dna_fix_maxval(dn, &setval, &maxval);
- if (LDAP_SUCCESS != ret) {
- slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
- "dna_get_next_value: no more IDs available!!\n");
- goto done;
- }
-
- /* verify the new value is actually free and get the first
- * one free if not */
- ret = dna_first_free_value(config_entry, &setval, maxval, increment);
- if (LDAP_SUCCESS != ret)
- goto done;
- }
-
- if (setval > maxval) {
- ret = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- newval = setval + increment;
-
- /* try for a new range or fail */
- if (newval > maxval) {
- ret = dna_fix_maxval(dn, &newval, &maxval);
- if (LDAP_SUCCESS != ret) {
- slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
- "dna_get_next_value: no more IDs available!!\n");
- goto done;
- }
- }
-
- /* try to set the new value */
-
- sprintf(new_value, "%llu", newval);
-
- delete_val[0] = old_value;
- delete_val[1] = 0;
-
- mod_delete.mod_op = LDAP_MOD_DELETE;
- mod_delete.mod_type = DNA_NEXTVAL;
- mod_delete.mod_values = delete_val;
-
- add_val[0] = new_value;
- add_val[1] = 0;
-
- mod_add.mod_op = LDAP_MOD_ADD;
- mod_add.mod_type = DNA_NEXTVAL;
- mod_add.mod_values = add_val;
-
- mods[0] = &mod_delete;
- mods[1] = &mod_add;
- mods[2] = 0;
-
- pb = slapi_pblock_new();
- if (NULL == pb) {
- ret = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- slapi_modify_internal_set_pb(pb, config_entry->dn,
- mods, 0, 0, getPluginID(), 0);
-
- slapi_modify_internal_pb(pb);
-
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
-
- slapi_pblock_destroy(pb);
- pb = NULL;
- slapi_ch_free_string(&interval);
- slapi_ch_free_string(&old_value);
-
- if (LDAP_SUCCESS == ret) {
- *next_value_ret = slapi_ch_smprintf("%llu", setval);
- if (NULL == *next_value_ret) {
- ret = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- dna_notice_allocation(dn, newval);
- goto done;
- }
-
- if (LDAP_NO_SUCH_ATTRIBUTE != ret) {
- /* not the result of a race
- to change the value
- */
- goto done;
- }
- }
-
- done:
-
- slapi_unlock_mutex(g_new_value_lock);
-
- if (LDAP_SUCCESS != ret)
- slapi_ch_free_string(&old_value);
-
- if (dn)
- slapi_sdn_free(&dn);
-
- if (e)
- slapi_entry_free(e);
-
- if (pb)
- slapi_pblock_destroy(pb);
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "<-- dna_get_next_value\n");
-
- return ret;
-}
-
-/* for mods and adds:
- where dn's are supplied, the closest in scope
- is used as long as the type and filter
- are identical - otherwise all matches count
-*/
-
-static int dna_pre_op(Slapi_PBlock * pb, int modtype)
-{
- char *dn = 0;
- PRCList *list = 0;
- struct configEntry *config_entry = 0;
- struct slapi_entry *e = 0;
- char *last_type = 0;
- char *value = 0;
- int generate = 0;
- Slapi_Mods *smods = 0;
- Slapi_Mod *smod = 0;
- LDAPMod **mods;
- int free_entry = 0;
- char *errstr = NULL;
- int ret = 0;
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "--> dna_pre_op\n");
-
- /* Just bail if we aren't ready to service requests yet. */
- if (!g_plugin_started)
- goto bail;
-
- if (0 == (dn = dna_get_dn(pb)))
- goto bail;
-
- if (dna_dn_is_config(dn))
- goto bail;
-
- if (LDAP_CHANGETYPE_ADD == modtype) {
- slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &e);
- } else {
- /* xxxPAR: Ideally SLAPI_MODIFY_EXISTING_ENTRY should be
- * available but it turns out that is only true if you are
- * a dbm backend pre-op plugin - lucky dbm backend pre-op
- * plugins.
- * I think that is wrong since the entry is useful for filter
- * tests and schema checks and this plugin shouldn't be limited
- * to a single backend type, but I don't want that fight right
- * now so we go get the entry here
- *
- slapi_pblock_get( pb, SLAPI_MODIFY_EXISTING_ENTRY, &e);
- */
- Slapi_DN *tmp_dn = slapi_sdn_new_dn_byref(dn);
- if (tmp_dn) {
- slapi_search_internal_get_entry(tmp_dn, 0, &e, getPluginID());
- slapi_sdn_free(&tmp_dn);
- free_entry = 1;
- }
-
- /* grab the mods - we'll put them back later with
- * our modifications appended
- */
- slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
- smods = slapi_mods_new();
- slapi_mods_init_passin(smods, mods);
- }
-
- if (0 == e)
- goto bailmod;
-
- dna_read_lock();
-
- if (!PR_CLIST_IS_EMPTY(dna_global_config)) {
- list = PR_LIST_HEAD(dna_global_config);
-
- while (list != dna_global_config && LDAP_SUCCESS == ret) {
- config_entry = (struct configEntry *) list;
-
- /* did we already service this type? */
- if (last_type) {
- if (!slapi_attr_type_cmp(config_entry->type, last_type, 1))
- goto next;
- }
-
- /* is the entry in scope? */
- if (config_entry->scope) {
- if (!slapi_dn_issuffix(dn, config_entry->scope))
- goto next;
- }
-
- /* does the entry match the filter? */
- if (config_entry->slapi_filter) {
- if (LDAP_SUCCESS != slapi_vattr_filter_test(pb,
- e,
- config_entry->
- slapi_filter, 0))
- goto next;
- }
-
-
- if (LDAP_CHANGETYPE_ADD == modtype) {
- /* does attribute contain the magic value
- or is the type not there?
- */
- value =
- slapi_entry_attr_get_charptr(e, config_entry->type);
- if ((value
- && !slapi_UTF8CASECMP(config_entry->generate, value))
- || 0 == value) {
- generate = 1;
- }
- } else {
- /* check mods for magic value */
- Slapi_Mod *next_mod = slapi_mod_new();
- smod = slapi_mods_get_first_smod(smods, next_mod);
- while (smod) {
- char *type = (char *)
- slapi_mod_get_type(smod);
-
- if (slapi_attr_types_equivalent(type,
- config_entry->type)) {
- struct berval *bv =
- slapi_mod_get_first_value(smod);
- int len = strlen(config_entry->generate);
-
-
- if (len == bv->bv_len) {
- if (!slapi_UTF8NCASECMP(bv->bv_val,
- config_entry->generate,
- len))
-
- generate = 1;
- break;
- }
- }
-
- slapi_mod_done(next_mod);
- smod = slapi_mods_get_next_smod(smods, next_mod);
- }
-
- slapi_mod_free(&next_mod);
- }
-
- if (generate) {
- char *new_value;
- int len;
-
- /* create the value to add */
- ret = dna_get_next_value(config_entry, &value);
- if (DNA_SUCCESS != ret) {
- errstr = slapi_ch_smprintf("Allocation of a new value for"
- " %s failed! Unable to proceed.",
- config_entry->type);
- break;
- }
-
- len = strlen(value) + 1;
- if (config_entry->prefix) {
- len += strlen(config_entry->prefix);
- }
-
- new_value = slapi_ch_malloc(len);
-
- if (config_entry->prefix) {
- strcpy(new_value, config_entry->prefix);
- strcat(new_value, value);
- } else
- strcpy(new_value, value);
-
- /* do the mod */
- if (LDAP_CHANGETYPE_ADD == modtype) {
- /* add - add to entry */
- slapi_entry_attr_set_charptr(e,
- config_entry->type,
- new_value);
- } else {
- /* mod - add to mods */
- slapi_mods_add_string(smods,
- LDAP_MOD_REPLACE,
- config_entry->type, new_value);
- }
-
- /* free up */
- slapi_ch_free_string(&value);
- slapi_ch_free_string(&new_value);
-
- /* make sure we don't generate for this
- * type again
- */
- if (LDAP_SUCCESS == ret) {
- last_type = config_entry->type;
- }
-
- generate = 0;
- }
- next:
- list = PR_NEXT_LINK(list);
- }
- }
-
- dna_unlock();
-
- bailmod:
- if (LDAP_CHANGETYPE_MODIFY == modtype) {
- /* these are the mods you made, really,
- * I didn't change them, honest, just had a quick look
- */
- mods = slapi_mods_get_ldapmods_passout(smods);
- slapi_pblock_set(pb, SLAPI_MODIFY_MODS, mods);
- slapi_mods_free(&smods);
- }
-
- bail:
-
- if (free_entry && e)
- slapi_entry_free(e);
-
- if (ret) {
- slapi_log_error(SLAPI_LOG_PLUGIN, DNA_PLUGIN_SUBSYSTEM,
- "dna_pre_op: operation failure [%d]\n", ret);
- slapi_send_ldap_result(pb, ret, NULL, errstr, 0, NULL);
- slapi_ch_free((void **)&errstr);
- ret = DNA_FAILURE;
- }
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "<-- dna_pre_op\n");
-
- return ret;
-}
-
-static int dna_add_pre_op(Slapi_PBlock * pb)
-{
- return dna_pre_op(pb, LDAP_CHANGETYPE_ADD);
-}
-
-static int dna_mod_pre_op(Slapi_PBlock * pb)
-{
- return dna_pre_op(pb, LDAP_CHANGETYPE_MODIFY);
-}
-
-static int dna_config_check_post_op(Slapi_PBlock * pb)
-{
- char *dn;
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "--> dna_config_check_post_op\n");
-
- if ((dn = dna_get_dn(pb))) {
- if (dna_dn_is_config(dn))
- loadPluginConfig();
- }
-
- slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
- "<-- dna_config_check_post_op\n");
-
- return 0;
-}
-
-/****************************************************
- End of
- Functions that actually do things other
- than config and startup
-****************************************************/
-
-/**
- * debug functions to print config
- */
-void dnaDumpConfig()
-{
- PRCList *list;
-
- dna_read_lock();
-
- if (!PR_CLIST_IS_EMPTY(dna_global_config)) {
- list = PR_LIST_HEAD(dna_global_config);
- while (list != dna_global_config) {
- dnaDumpConfigEntry((struct configEntry *) list);
- list = PR_NEXT_LINK(list);
- }
- }
-
- dna_unlock();
-}
-
-
-void dnaDumpConfigEntry(struct configEntry * entry)
-{
- printf("<- type --------------> %s\n", entry->type);
- printf("<---- prefix ---------> %s\n", entry->prefix);
- printf("<---- next value -----> %lu\n", entry->nextval);
- printf("<---- interval -------> %lu\n", entry->interval);
- printf("<---- generate flag --> %s\n", entry->generate);
-}