summaryrefslogtreecommitdiffstats
path: root/src/backend.c
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin.dahyabhai@pobox.com>2008-05-09 17:30:14 -0400
committerNalin Dahyabhai <nalin.dahyabhai@pobox.com>2008-05-09 17:30:14 -0400
commite678eda5091c418b8e0fde4a827ca35171bc178c (patch)
treeb7537c3abcc9a7b85ea7fe14318b22f7b413d981 /src/backend.c
parent4f3f702d8a10ca2cf3a368f6e56300fe8e59a688 (diff)
downloadslapi-nis-e678eda5091c418b8e0fde4a827ca35171bc178c.tar.gz
slapi-nis-e678eda5091c418b8e0fde4a827ca35171bc178c.tar.xz
slapi-nis-e678eda5091c418b8e0fde4a827ca35171bc178c.zip
- learn to iterate over maps
- rename visited lists to related lists - handle NULL related ID lists - fix map semantics so that it won't try to take ownership of key/value data - set up map backend data - start doing proper adds/removes in post-op callbacks
Diffstat (limited to 'src/backend.c')
-rw-r--r--src/backend.c223
1 files changed, 175 insertions, 48 deletions
diff --git a/src/backend.c b/src/backend.c
index b52b7f0..28f6275 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -17,51 +17,106 @@
#include "map.h"
#include "defaults.h"
-/* Given a map/domain entry, add it to the map. */
+/* The data we ask the map cache to keep, for us, for each map. */
struct backend_map_entry_cb_data {
struct plugin_state *state;
- const char *domain, *map, *key, *value;
+ char *domain, *map, *key_attr, *value_fmt;
};
+static struct backend_map_entry_cb_data *
+backend_copy_cb_data(const struct backend_map_entry_cb_data *data)
+{
+ struct backend_map_entry_cb_data *ret;
+ ret = malloc(sizeof(*ret));
+ if (ret == NULL) {
+ return NULL;
+ }
+ ret->state = data->state;
+ ret->domain = strdup(data->domain);
+ ret->map = strdup(data->map);
+ ret->key_attr = strdup(data->key_attr);
+ ret->value_fmt = strdup(data->value_fmt);
+ if ((ret->domain == NULL) ||
+ (ret->map == NULL) ||
+ (ret->key_attr == NULL) ||
+ (ret->value_fmt == NULL)) {
+ free(ret->domain);
+ free(ret->map);
+ free(ret->key_attr);
+ free(ret->value_fmt);
+ free(ret);
+ return NULL;
+ }
+ return ret;
+}
+
+static void
+backend_free_cb_data(void *data)
+{
+ struct backend_map_entry_cb_data *cb_data = data;
+ if (cb_data != NULL) {
+ free(cb_data->domain);
+ free(cb_data->map);
+ free(cb_data->key_attr);
+ free(cb_data->value_fmt);
+ free(cb_data);
+ }
+}
+
+/* Given a map-entry directory entry, determine which keys it should have,
+ * determine which value should be associated with those keys, and add them to
+ * the map cache. */
static int
backend_map_entry_cb(Slapi_Entry *e, void *callback_data)
{
struct backend_map_entry_cb_data *data;
- char **key, **value, *dn;
+ char *key, *value, *dn, **visited_dn;
int i, j;
data = callback_data;
- key = slapi_entry_attr_get_charray(e, data->key);
- value = slapi_entry_attr_get_charray(e, data->value);
+ /* Pull out the name of the attribute which holds the key. */
+ key = slapi_entry_attr_get_charptr(e, data->key_attr);
+ /* Pull out the value format string and generate the value. XXX */
+ value = slapi_entry_attr_get_charptr(e, data->value_fmt);
+ /* Pull together the DN of this entry and the others we peeked at. */
dn = slapi_entry_get_dn(e);
- for (i = 0; (key != NULL) && (key[i] != NULL); i++) {
- for (j = 0; (value != NULL) && (value[j] != NULL); j++) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- data->state->plugin_desc->spd_id,
- "setting domain/map/key/value "
- "\"%s\"/\"%s\"/\"%s\"(\"%s\")=\"%s\"\n",
- data->domain, data->map,
- key[i], dn, value[j]);
- map_data_set_entry(data->state, data->domain, data->map,
- dn, NULL,
- -1, strdup(key[i]),
- -1, strdup(value[j]));
- }
- if (j == 0) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- data->state->plugin_desc->spd_id,
- "no value for %s\n", dn);
- }
- }
- if (i == 0) {
+ visited_dn = NULL;
+ /* If we actually generated a value, then set it for all keys. */
+ if ((key != NULL) && (value != NULL)) {
+ /* For each key, set the value. */
slapi_log_error(SLAPI_LOG_PLUGIN,
data->state->plugin_desc->spd_id,
- "no key for %s\n", dn);
+ "setting domain/map/key/value "
+ "\"%s\"/\"%s\"/\"%s\"(\"%s\")=\"%s\"\n",
+ data->domain, data->map,
+ key, dn, value);
+ map_data_set_entry(data->state, data->domain, data->map,
+ dn, (const char **) visited_dn,
+ -1, key,
+ -1, value);
+ } else {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ data->state->plugin_desc->spd_id,
+ "no value for %s\n", dn);
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ data->state->plugin_desc->spd_id,
+ "unsetting domain/map/id"
+ "\"%s\"/\"%s\"/(\"%s\")\n",
+ data->domain, data->map, dn);
+ map_data_unset_entry_id(data->state,
+ data->domain, data->map,
+ dn);
}
- slapi_ch_array_free(value);
- slapi_ch_array_free(key);
+ slapi_ch_free_string(&value);
+ slapi_ch_free_string(&key);
return 0;
}
+/*
+ * Generate a copy of the filter string, with specific sequences replaced:
+ * %d -> name of the domain
+ * %m -> name of the map
+ * %% -> literal '%'
+ */
static char *
backend_map_config_filter(const char *fmt, const char *domain, const char *map)
{
@@ -121,48 +176,62 @@ backend_map_config_filter(const char *fmt, const char *domain, const char *map)
return ret;
}
+/* Given a directory server entry which represents a map's configuration, set
+ * up and populate the map. */
static int
backend_map_config_entry(struct plugin_state *state, Slapi_Entry *e,
const char *domain, const char *map)
{
Slapi_PBlock *pb;
char **base;
- int i, scope;
+ int i;
char *entry_filter, *use_entry_filter, *key_attribute, *value_attribute;
- const char *use_key_attribute, *use_value_attribute;
- char *attrs[3]; /* XXX */
+ char *use_key_attribute, *use_value_attribute;
+ char *use_attrs[3]; /* XXX */
struct backend_map_entry_cb_data cb_data;
pb = slapi_pblock_new();
+ /* Read the NIS entry search base, entry search filter, and the names
+ * of the key and value attributes. */
base = slapi_entry_attr_get_charray(e, "base");
entry_filter = slapi_entry_attr_get_charptr(e, "filter");
key_attribute = slapi_entry_attr_get_charptr(e, "key");
value_attribute = slapi_entry_attr_get_charptr(e, "value");
+ /* Perform substitutions on the filter, so that it can include the map
+ * name without having to explicitly list it. We need this because
+ * RFC2307bis actually stores the map name in each entry, so it's
+ * useful to be able to filter on it. */
use_entry_filter = backend_map_config_filter(entry_filter ?
entry_filter :
DEFAULT_ENTRY_FILTER,
domain, map);
+ /* If the key and value attributes aren't set, we'll use compiled-in
+ * defaults. */
use_key_attribute = key_attribute ?
key_attribute :
DEFAULT_KEY_ATTRIBUTE;
use_value_attribute = value_attribute ?
value_attribute :
DEFAULT_VALUE_ATTRIBUTE;
- attrs[0] = (char *) use_key_attribute; /* XXX */
- attrs[1] = (char *) use_value_attribute; /* XXX */
- attrs[2] = NULL; /* XXX */
- scope = LDAP_SCOPE_SUB;
+ /* Now get ready to search for entries which need to be in the map. */
+ use_attrs[0] = use_key_attribute; /* XXX */
+ use_attrs[1] = use_value_attribute; /* XXX */
+ use_attrs[2] = NULL; /* XXX */
cb_data.state = state;
- cb_data.domain = domain;
- cb_data.map = map;
- cb_data.key = use_key_attribute;
- cb_data.value = use_value_attribute;
+ cb_data.domain = (char *) domain;
+ cb_data.map = (char *) map;
+ cb_data.key_attr = use_key_attribute;
+ cb_data.value_fmt = use_value_attribute;
slapi_log_error(SLAPI_LOG_PLUGIN,
state->plugin_desc->spd_id,
"initializing map %s in %s (2)\n",
map, domain);
- map_data_set_map(state, domain, map, NULL, NULL);
+ map_data_set_map(state, domain, map,
+ backend_copy_cb_data(&cb_data),
+ &backend_free_cb_data);
map_data_clear_map(state, domain, map);
+ /* Search under each base in turn, adding the matching directory
+ * entries to the NIS maps. */
for (i = 0; (base != NULL) && (base[i] != NULL); i++) {
slapi_log_error(SLAPI_LOG_PLUGIN,
state->plugin_desc->spd_id,
@@ -170,9 +239,9 @@ backend_map_config_entry(struct plugin_state *state, Slapi_Entry *e,
base[i], use_entry_filter);
slapi_search_internal_set_pb(pb,
base[i],
- scope,
+ LDAP_SCOPE_SUB,
use_entry_filter,
- attrs, 0,
+ use_attrs, 0,
NULL,
NULL,
state->plugin_identity,
@@ -183,6 +252,7 @@ backend_map_config_entry(struct plugin_state *state, Slapi_Entry *e,
NULL);
slapi_free_search_results_internal(pb);
}
+ /* Clean up. */
free(use_entry_filter);
slapi_ch_free_string(&value_attribute);
slapi_ch_free_string(&key_attribute);
@@ -192,6 +262,9 @@ backend_map_config_entry(struct plugin_state *state, Slapi_Entry *e,
return 0;
}
+/* Process a map configuration directory entry. Pull out the domain and map
+ * names which are valid for this configuration and configure such a map for
+ * each in turn. */
static int
backend_map_config_entry_cb(Slapi_Entry *e, void *callback_data)
{
@@ -246,16 +319,36 @@ backend_startup(struct plugin_state *state)
}
/* Our postop callbacks. */
+
+/* Add any map entries which correspond to a directory server entry in this
+ * map. */
+static PRBool
+backend_add_entry_cb(const char *domain, const char *map, void *backend_data,
+ void *cbdata)
+{
+ char *dn;
+ struct backend_map_entry_cb_data *data;
+ data = backend_data;
+ dn = cbdata;
+ return PR_TRUE;
+}
+
int
backend_add_cb(Slapi_PBlock *pb)
{
struct plugin_state *state;
- char *dn, *id;
+ char *dn;
slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state);
slapi_pblock_get(pb, SLAPI_TARGET_DN, &dn);
- slapi_pblock_get(pb, SLAPI_TARGET_UNIQUEID, &id);
slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
- "added \"%s\" (\"%s\")\n", dn, id);
+ "added \"%s\"\n", dn);
+ /* Add map entries which corresponded to this directory server
+ * entry. */
+ if (!map_data_foreach_map(state, NULL, backend_add_entry_cb, dn)) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ "error adding map entries corresponding to "
+ "\"%s\"\n", dn);
+ }
return 0;
}
@@ -285,16 +378,38 @@ backend_modrdn_cb(Slapi_PBlock *pb)
return 0;
}
+/* Delete any map entries which correspond to a directory server entry in this
+ * map. */
+static PRBool
+backend_delete_entry_cb(const char *domain, const char *map, void *backend_data,
+ void *cbdata)
+{
+ char *dn;
+ struct backend_map_entry_cb_data *data;
+ data = backend_data;
+ dn = cbdata;
+ map_data_unset_entry_id(data->state, domain, map, dn);
+ return PR_TRUE;
+}
+
+/* Called by the server when a directory server entry is deleted. */
int
backend_delete_cb(Slapi_PBlock *pb)
{
struct plugin_state *state;
- char *dn, *id;
+ char *dn;
slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state);
slapi_pblock_get(pb, SLAPI_TARGET_DN, &dn);
- slapi_pblock_get(pb, SLAPI_TARGET_UNIQUEID, &id);
slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
- "deleted \"%s\" (\"%s\")\n", dn, id);
+ "deleted \"%s\" (\"%s\")\n", dn);
+ /* Remove map entries which corresponded to this directory server
+ * entry. */
+ if (!map_data_foreach_map(state, NULL, backend_delete_entry_cb, dn)) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ "error removing map entries corresponding to "
+ "\"%s\"\n", dn);
+ }
+ /* If it's a map configuration entry, remove the map. XXX */
return 0;
}
@@ -325,3 +440,15 @@ backend_init(Slapi_PBlock *pb, struct plugin_state *state)
"error hooking up delete callback\n");
}
}
+
+void *
+xmemdup(char *region, int size)
+{
+ char *ret;
+ ret = malloc(size + 1);
+ if (ret != NULL) {
+ memcpy(ret, region, size);
+ ret[size] = '\0';
+ }
+ return ret;
+}