summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend.c87
-rw-r--r--src/backend.h3
-rw-r--r--src/dummymap.c13
-rw-r--r--src/map.c68
-rw-r--r--src/map.h5
-rw-r--r--src/nis.c6
6 files changed, 147 insertions, 35 deletions
diff --git a/src/backend.c b/src/backend.c
index bb4d38d..a004eae 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -24,6 +24,66 @@ struct backend_map_data {
char *domain, *map, **bases, *filter, *key_fmt, *value_fmt;
};
+/* Read the name of the NIS master. */
+void
+backend_free_master_name(struct plugin_state *state, char *master)
+{
+ free(master);
+}
+
+int
+backend_read_master_name(struct plugin_state *state, char **master)
+{
+ Slapi_DN *config_dn;
+ Slapi_Entry *config;
+ Slapi_ValueSet *values;
+ Slapi_Value *value;
+ char *attrs[] = {"nsslapd-localhost", NULL}, *actual_attr;
+ const char *cvalue;
+ int disposition, buffer_flags;
+ *master = NULL;
+ /* Try to read our name from the top-level configuration node. */
+ config_dn = slapi_sdn_new_dn_byval("cn=config");
+ if (config_dn == NULL) {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ state->plugin_desc->spd_id,
+ "backend_master_name: "
+ "error parsing \"cn=config\"\n");
+ return -1;
+ }
+ config = NULL;
+ slapi_search_internal_get_entry(config_dn, attrs, &config,
+ state->plugin_identity);
+ if (config == NULL) {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ state->plugin_desc->spd_id,
+ "backend_master_name: failure reading "
+ "\"cn=config\"");
+ slapi_sdn_free(&config_dn);
+ return -1;
+ }
+ slapi_sdn_free(&config_dn);
+ /* Pull out the attribute. */
+ if (slapi_vattr_values_get(config, attrs[0], &values,
+ &disposition, &actual_attr,
+ 0, &buffer_flags) == 0) {
+ if (slapi_valueset_first_value(values, &value) == 0) {
+ cvalue = slapi_value_get_string(value);
+ if (cvalue != NULL) {
+ *master = strdup(cvalue);
+ }
+ } else {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ state->plugin_desc->spd_id,
+ "backend_master_name: no \"%s\" value "
+ "for \"cn=config\"",
+ attrs[0]);
+ }
+ slapi_vattr_values_free(&values, &actual_attr, buffer_flags);
+ }
+ slapi_entry_free(config);
+ return (*master != NULL) ? 0 : -1;
+}
static char **
backend_dup_strlist(char **strlist)
{
@@ -363,7 +423,8 @@ backend_startup(struct plugin_state *state)
/* Our postoperation callbacks. */
static PRBool
-backend_entry_matches_map(struct backend_map_data *map_data, Slapi_Entry *e)
+backend_entry_matches_map(struct backend_map_data *map_data,
+ Slapi_PBlock *pb, Slapi_Entry *e)
{
Slapi_DN *base_sdn;
const Slapi_DN *entry_sdn;
@@ -406,7 +467,7 @@ backend_entry_matches_map(struct backend_map_data *map_data, Slapi_Entry *e)
if (filter == NULL) {
return PR_FALSE;
} else {
- if (slapi_filter_test_simple(e, filter) != 0) {
+ if (slapi_vattr_filter_test(pb, e, filter, 0) != 0) {
/* Didn't match -- return. */
slapi_filter_free(filter, 1);
return PR_FALSE;
@@ -440,7 +501,7 @@ backend_add_entry_cb(const char *domain, const char *map, void *backend_data,
cbdata = cbdata_ptr;
/* If the entry doesn't match the map, skip it. */
- if (!backend_entry_matches_map(map_data, cbdata->e)) {
+ if (!backend_entry_matches_map(map_data, cbdata->pb, cbdata->e)) {
slapi_log_error(SLAPI_LOG_PLUGIN,
map_data->state->plugin_desc->spd_id,
"entry \"%s\" does not belong in "
@@ -537,7 +598,7 @@ backend_modify_entry_cb(const char *domain, const char *map, void *backend_data,
cbdata = cbdata_ptr;
/* If the entry doesn't match the map, skip it. */
- if (!backend_entry_matches_map(map_data, cbdata->e)) {
+ if (!backend_entry_matches_map(map_data, cbdata->pb, cbdata->e)) {
slapi_log_error(SLAPI_LOG_PLUGIN,
map_data->state->plugin_desc->spd_id,
"clearing domain/map/id "
@@ -644,8 +705,10 @@ backend_modrdn_entry_cb(const char *domain, const char *map, void *backend_data,
map_data = backend_data;
cbdata = cbdata_ptr;
- matched_pre = backend_entry_matches_map(map_data, cbdata->e_pre);
- matched_post = backend_entry_matches_map(map_data, cbdata->e_post);
+ matched_pre = backend_entry_matches_map(map_data,
+ cbdata->pb, cbdata->e_pre);
+ matched_post = backend_entry_matches_map(map_data,
+ cbdata->pb, cbdata->e_post);
/* Pull out the key and value for the old entry. */
key_pre = format_get_data(cbdata->state, cbdata->pb, cbdata->e_pre,
@@ -855,15 +918,3 @@ 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;
-}
diff --git a/src/backend.h b/src/backend.h
index ed6bcd5..260204b 100644
--- a/src/backend.h
+++ b/src/backend.h
@@ -1,6 +1,7 @@
/* Initialize maps. */
struct plugin_state;
struct slapi_pblock;
+int backend_read_master_name(struct plugin_state *state, char **master);
+void backend_free_master_name(struct plugin_state *state, char *master);
void backend_startup(struct plugin_state *state);
void backend_init(struct slapi_pblock *pb, struct plugin_state *state);
-void *xmemdup(char *region, int size);
diff --git a/src/dummymap.c b/src/dummymap.c
index 104fdc6..7ba1728 100644
--- a/src/dummymap.c
+++ b/src/dummymap.c
@@ -63,14 +63,23 @@ struct domain domains[] = {
{NULL, NULL},
};
-void
+int
map_startup(struct plugin_state *state)
{
+ return 0;
}
-void
+int
map_init(struct slapi_pblock *pb, struct plugin_state *state)
{
+ return 0;
+}
+
+int
+map_master_name(struct plugin_state *state, const char **master)
+{
+ *master = "me, right here";
+ return 0;
}
bool_t
diff --git a/src/map.c b/src/map.c
index 3de4a7f..96b78d4 100644
--- a/src/map.c
+++ b/src/map.c
@@ -3,6 +3,7 @@
#endif
#include <sys/types.h>
+#include <pthread.h>
#include <search.h>
#include <stdlib.h>
#include <string.h>
@@ -22,21 +23,32 @@
/* The singleton for the cache. */
struct {
+ char *master;
struct domain {
char *name;
struct map {
+ /* Map name and order. */
char *name;
time_t last_changed;
+ /* Individual map entries. */
struct map_entry {
+ /* Links to previous and next nodes in the
+ * list. */
struct map_entry *prev, *next;
+ /* The name of the backend entry for this
+ * entry, and the names of others which
+ * contributed to the value. */
char *id, **related_ids;
+ /* Key and value. */
char *key;
unsigned int key_len;
char *value;
unsigned int value_len;
} *entries;
+ /* Search trees to speed up searches for entries. */
void *key_tree;
void *id_tree;
+ /* Callback data supplied by the map writer. */
void *backend_data;
void (*free_backend_data)(void *backend_data);
} *maps;
@@ -45,6 +57,18 @@ struct {
int n_domains;
} map_data;
+static void *
+xmemdup(char *region, int size)
+{
+ char *ret;
+ ret = malloc(size + 1);
+ if (ret != NULL) {
+ memcpy(ret, region, size);
+ ret[size] = '\0';
+ }
+ return ret;
+}
+
/* Comparison functions used by the tree storage facility. */
static int
t_compare_entry_by_id(const void *p1, const void *p2)
@@ -130,12 +154,9 @@ map_data_find_entry(struct plugin_state *state,
const char *domain_name, const char *map_name,
unsigned int key_len, const char *key)
{
- return map_data_find_map_entry(state,
- map_data_find_map(state,
- domain_name,
- map_name),
- key_len,
- key);
+ struct map *map;
+ map = map_data_find_map(state, domain_name, map_name);
+ return map_data_find_map_entry(state, map, key_len, key);
}
static struct map_entry *
@@ -345,6 +366,27 @@ map_supports_map(struct plugin_state *state,
return TRUE;
}
+/* Query function: return the name of this master. */
+int
+map_master_name(struct plugin_state *state, const char **master)
+{
+ char *tmp, hostname[HOST_NAME_MAX + 1];
+ if (backend_read_master_name(state, &tmp) == 0) {
+ free(map_data.master);
+ map_data.master = strdup(tmp);
+ backend_free_master_name(state, tmp);
+ } else {
+ memset(hostname, '\0', sizeof(hostname));
+ if (gethostname(hostname, sizeof(hostname)) != 0) {
+ snprintf(hostname, sizeof(hostname), "%s", "localhost");
+ }
+ free(map_data.master);
+ map_data.master = strdup(hostname);
+ }
+ *master = map_data.master;
+ return 0;
+}
+
/* Query function: return an indication of the map's age. Should never
* decrease. */
PRBool
@@ -456,8 +498,9 @@ void
map_data_clear_map(struct plugin_state *state,
const char *domain_name, const char *map_name)
{
- map_data_clear_map_map(state,
- map_data_find_map(state, domain_name, map_name));
+ struct map *map;
+ map = map_data_find_map(state, domain_name, map_name);
+ map_data_clear_map_map(state, map);
}
/* Remove a map from the configuration, removing its domain record if the map
@@ -730,18 +773,21 @@ map_data_set_entry(struct plugin_state *state,
/* XXX */
}
}
+ map->last_changed = time(NULL);
}
- map->last_changed = time(NULL);
}
-void
+int
map_startup(struct plugin_state *state)
{
backend_startup(state);
+ return 0;
}
-void
+int
map_init(struct slapi_pblock *pb, struct plugin_state *state)
{
+ memset(&map_data, 0, sizeof(map_data));
backend_init(pb, state);
+ return 0;
}
diff --git a/src/map.h b/src/map.h
index cc479b0..6775ccc 100644
--- a/src/map.h
+++ b/src/map.h
@@ -1,8 +1,9 @@
struct plugin_state;
struct slapi_pblock;
/* Functions to pull data out of maps. */
-void map_startup(struct plugin_state *state);
-void map_init(struct slapi_pblock *pb, struct plugin_state *state);
+int map_startup(struct plugin_state *state);
+int map_init(struct slapi_pblock *pb, struct plugin_state *state);
+int map_master_name(struct plugin_state *state, const char **master);
PRBool map_supports_domain(struct plugin_state *state,
const char *domain,
PRBool *supported);
diff --git a/src/nis.c b/src/nis.c
index 174824f..e0f1dad 100644
--- a/src/nis.c
+++ b/src/nis.c
@@ -285,11 +285,15 @@ nis_master(struct plugin_state *state,
struct ypresp_master *reply_master)
{
struct ypreq_nokey req_nokey;
+ const char *master;
memset(&req_nokey, 0, sizeof(req_nokey));
memset(reply_master, 0, sizeof(*reply_master));
if (xdr_ypreq_nokey(request_xdrs, &req_nokey)) {
reply_master->status = YP_TRUE;
- reply_master->master = "me, right here"; /* XXX */
+ if (map_master_name(state, &master) != 0) {
+ master = "localhost";
+ }
+ reply_master->master = (char *) master;
slapi_log_error(SLAPI_LOG_PLUGIN,
state->plugin_desc->spd_id,
"master(%s/%s) -> %s\n",