diff options
author | Nalin Dahyabhai <nalin.dahyabhai@pobox.com> | 2008-06-06 16:55:40 -0400 |
---|---|---|
committer | Nalin Dahyabhai <nalin.dahyabhai@pobox.com> | 2008-06-06 16:55:40 -0400 |
commit | 0f8605f4d290a295c6794c973da8a74b90851085 (patch) | |
tree | d97487932d4ea3c0f433c0f4230865f923961620 /src | |
parent | 72c914963daf128d087f97d7f86e84f662c73ba5 (diff) | |
download | slapi-nis-0f8605f4d290a295c6794c973da8a74b90851085.tar.gz slapi-nis-0f8605f4d290a295c6794c973da8a74b90851085.tar.xz slapi-nis-0f8605f4d290a295c6794c973da8a74b90851085.zip |
- use inrefs and refs to handle references when we're doing updates
Diffstat (limited to 'src')
-rw-r--r-- | src/backend.c | 336 |
1 files changed, 201 insertions, 135 deletions
diff --git a/src/backend.c b/src/backend.c index e7d3fdd..5eebcc5 100644 --- a/src/backend.c +++ b/src/backend.c @@ -51,7 +51,8 @@ struct backend_map_data { struct plugin_state *state; char *domain, *map, **bases, *entry_filter, *key_format, *value_format; - char **referred; + char **ref_attrs; + struct format_inref_attr **inref_attrs; }; /* Read the name of the NIS master. */ @@ -159,7 +160,8 @@ backend_free_map_data_contents(void *data) free(map_data->domain); free(map_data->map); free(map_data->bases); - free(map_data->referred); + format_free_attr_list(map_data->ref_attrs); + format_free_inref_attrs(map_data->inref_attrs); free(map_data->entry_filter); free(map_data->key_format); free(map_data->value_format); @@ -184,9 +186,12 @@ backend_copy_cb_data(const struct backend_map_data *data) ret->domain = strdup(data->domain); ret->map = strdup(data->map); ret->bases = backend_dup_strlist(data->bases); - ret->referred = data->referred ? - backend_dup_strlist(data->referred) : - NULL; + ret->ref_attrs = data->ref_attrs ? + format_dup_attr_list(data->ref_attrs) : + NULL; + ret->inref_attrs = data->inref_attrs ? + format_dup_inref_attrs(data->inref_attrs) : + NULL; ret->entry_filter = strdup(data->entry_filter); ret->key_format = strdup(data->key_format); ret->value_format = strdup(data->value_format); @@ -208,15 +213,16 @@ static int backend_map_config_entry_add_one_cb(Slapi_Entry *e, void *callback_data) { struct backend_map_data *data; - char *key, *value, *ndn, **visited_dn_list; + char *key, *value, *ndn; int i, j; data = callback_data; /* Pull out the key and value for the entry. */ - visited_dn_list = NULL; key = format_get_data(data->state, NULL, e, data->domain, data->map, - data->key_format, &visited_dn_list); + data->key_format, + &data->ref_attrs, &data->inref_attrs); value = format_get_data(data->state, NULL, e, data->domain, data->map, - data->value_format, &visited_dn_list); + data->value_format, + &data->ref_attrs, &data->inref_attrs); /* Pull out the NDN of this entry. */ ndn = slapi_entry_get_ndn(e); /* If we actually generated a value, then set it, otherwise clear it in @@ -228,8 +234,7 @@ backend_map_config_entry_add_one_cb(Slapi_Entry *e, void *callback_data) "\"%s\"/\"%s\"/\"%s\"(\"%s\")=\"%s\"\n", data->domain, data->map, key, ndn, value); - map_data_set_entry(data->state, data->domain, data->map, - ndn, (const char **) visited_dn_list, + map_data_set_entry(data->state, data->domain, data->map, ndn, -1, key, -1, value); } else { @@ -242,17 +247,23 @@ backend_map_config_entry_add_one_cb(Slapi_Entry *e, void *callback_data) data->domain, data->map, ndn); } - format_free_ndn_list(visited_dn_list); format_free_data(value); format_free_data(key); return 0; } +static int +backend_map_config_entry_set_one_cb(Slapi_Entry *e, void *cbdata) +{ + backend_map_config_entry_add_one_cb(e, cbdata); + return 0; +} + static void backend_map_config_entry_set_one(Slapi_Entry *e, struct backend_map_data *map_data) { - backend_map_config_entry_add_one_cb(e, map_data); + backend_map_config_entry_set_one_cb(e, map_data); } static void @@ -357,17 +368,15 @@ backend_map_config_read_config(struct plugin_state *state, Slapi_Entry *e, struct backend_map_data *ret) { const char *default_filter, *default_key_format, *default_value_format; - const char **default_referred; - char **bases, *entry_filter, *key_format, *value_format, **referred; + char **bases, *entry_filter, *key_format, *value_format; + char **ref_attrs; + struct format_inref_attr **inref_attrs; char **use_bases, *use_entry_filter, *use_key_format, *use_value_format; - char **use_referred; /* Read the hard-coded defaults for a map with this name. */ defaults_get_map_config(map, &default_filter, - &default_key_format, &default_value_format, - &default_referred); + &default_key_format, &default_value_format); /* Read the values from the configuration entry. */ bases = slapi_entry_attr_get_charray(e, "base"); - referred = slapi_entry_attr_get_charray(e, "referred"); entry_filter = slapi_entry_attr_get_charptr(e, "filter"); key_format = slapi_entry_attr_get_charptr(e, "keyFormat"); value_format = slapi_entry_attr_get_charptr(e, "valueFormat"); @@ -386,26 +395,21 @@ backend_map_config_read_config(struct plugin_state *state, Slapi_Entry *e, strdup(value_format) : strdup(default_value_format); use_bases = backend_dup_strlist(bases); - use_referred = referred ? - backend_dup_strlist(referred) : - (default_referred ? - backend_dup_strlist((char **) default_referred) : - NULL); /* Free the values we read from the entry. */ slapi_ch_free_string(&value_format); slapi_ch_free_string(&key_format); slapi_ch_free_string(&entry_filter); - slapi_ch_array_free(referred); slapi_ch_array_free(bases); /* Populate the returned structure. */ ret->state = state; ret->domain = strdup(domain); ret->map = strdup(map); ret->bases = use_bases; - ret->referred = use_referred; ret->entry_filter = use_entry_filter; ret->key_format = use_key_format; ret->value_format = use_value_format; + ret->ref_attrs = NULL; + ret->inref_attrs = NULL; slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "initializing map %s in %s (3): " @@ -424,7 +428,7 @@ backend_map_config_entry_add_one(struct plugin_state *state, Slapi_Entry *e, { Slapi_PBlock *pb; int i; - struct backend_map_data cb_data; + struct backend_map_data cb_data, *map_cb_data; pb = slapi_pblock_new(); backend_map_config_read_config(state, e, domain, map, &cb_data); @@ -432,36 +436,37 @@ backend_map_config_entry_add_one(struct plugin_state *state, Slapi_Entry *e, state->plugin_desc->spd_id, "initializing map %s in %s (2)\n", map, domain); + map_cb_data = backend_copy_cb_data(&cb_data); + backend_free_map_data_contents(&cb_data); map_data_set_map(state, domain, map, - backend_copy_cb_data(&cb_data), - &backend_free_map_data); + map_cb_data, &backend_free_map_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; - (cb_data.bases != NULL) && (cb_data.bases[i] != NULL); + (map_cb_data->bases != NULL) && (map_cb_data->bases[i] != NULL); i++) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, - "searching %s for %s\n", - cb_data.bases[i], cb_data.entry_filter); + "searching '%s' for '%s'\n", + map_cb_data->bases[i], + map_cb_data->entry_filter); slapi_search_internal_set_pb(pb, - cb_data.bases[i], + map_cb_data->bases[i], LDAP_SCOPE_SUB, - cb_data.entry_filter, + map_cb_data->entry_filter, NULL, FALSE, NULL, NULL, state->plugin_identity, 0); - slapi_search_internal_callback_pb(pb, &cb_data, + slapi_search_internal_callback_pb(pb, map_cb_data, NULL, backend_map_config_entry_add_one_cb, NULL); slapi_free_search_results_internal(pb); } /* Clean up. */ - backend_free_map_data_contents(&cb_data); slapi_pblock_destroy(pb); return 0; } @@ -499,11 +504,12 @@ backend_read_params(struct plugin_state *state) Slapi_ValueSet *values; Slapi_Value *value; char *actual_attr, *cvalue; - int disposition, buffer_flags, ivalue, i; + int disposition, buffer_flags, ivalue, i, j; unsigned int uvalue; char *attrs[] = { "nis-plugin-max-value-size", "nis-plugin-max-dgram-size", + "nis-plugin-securenet", NULL, }; /* Try to read our name from the top-level configuration node. */ @@ -531,7 +537,9 @@ backend_read_params(struct plugin_state *state) if (slapi_vattr_values_get(our_entry, attrs[i], &values, &disposition, &actual_attr, 0, &buffer_flags) == 0) { - if (slapi_valueset_first_value(values, &value) == 0) { + value = NULL; + j = slapi_valueset_first_value(values, &value); + if (j != -1) { switch (i) { case 0: /* max value size */ uvalue = slapi_value_get_uint(value); @@ -563,6 +571,11 @@ backend_read_params(struct plugin_state *state) "size %u\n", state->max_dgram_size); break; + case 2: /* securenet entry */ + while (j != -1) { + j = slapi_valueset_next_value(values, j, &value); + } + break; default: break; } @@ -743,7 +756,7 @@ backend_get_map_config(struct plugin_state *state, 0); cbdata.bases = NULL; cbdata.state = state; - defaults_get_map_config(map, &default_filter, NULL, NULL, NULL); + defaults_get_map_config(map, &default_filter, NULL, NULL); cbdata.entry_filter = strdup(default_filter); slapi_search_internal_callback_pb(pb, &cbdata, NULL, @@ -881,71 +894,162 @@ backend_entry_is_a_map(struct plugin_state *state, /* Update any entries to which the passed-in entry in the passed-in map refers * to, if the referred-to entry is in this map. Everybody got that? */ -struct backend_update_referred_to_entries_cbdata { - struct backend_map_data *map_data; +struct backend_update_references_cbdata { + Slapi_PBlock *pb; Slapi_Entry *e; }; + static bool_t -backend_update_referred_to_entries_cb(const char *domain, const char *map, - void *backend_data, void *cbdata_ptr) +backend_update_references_cb(const char *domain, const char *map, + void *backend_data, void *cbdata_ptr) { + struct plugin_state *state; struct backend_map_data *map_data; - struct backend_update_referred_to_entries_cbdata *cbdata; + struct backend_update_references_cbdata *cbdata; Slapi_DN *referred_to_sdn; Slapi_ValueSet *values; Slapi_Value *value; - char **referred_to_dn, **referred, *actual_attr; + char **referred_to_dn, **ref_attrs, *actual_attr, *filter; + struct format_inref_attr **inref_attrs; const char *ndn, *dn; - int i, j, disposition, buffer_flags; + int i, j, disposition, buffer_flags, filter_size, n_ref_attrs; map_data = backend_data; cbdata = cbdata_ptr; + state = map_data->state; - /* Allocate the DN we'll use to hold values. */ + /* For every entry in this map which refers to this entry using + * a DN stored in an attribute, update that entry. */ + + /* Build a filter with all of these attributes and this entry's DN. */ + ref_attrs = map_data->ref_attrs; + for (i = 0; (ref_attrs != NULL) && (ref_attrs[i] != NULL); i++) { + continue; + } + n_ref_attrs = i; + if (n_ref_attrs > 0) { + filter_size = strlen("(&(|))") + + strlen(map_data->entry_filter) + + 1; + ndn = slapi_entry_get_ndn(cbdata->e); + for (i = 0; + (ref_attrs != NULL) && (ref_attrs[i] != NULL); + i++) { + filter_size += (strlen("(=)") + + strlen(ref_attrs[i]) + + strlen(ndn)); + } + filter = malloc(filter_size); + if (filter == NULL) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "error building filter for " + "updating entries\n"); + return TRUE; + } + sprintf(filter, "(&%s(|", map_data->entry_filter); + for (i = 0; + (ref_attrs != NULL) && (ref_attrs[i] != NULL); + i++) { + sprintf(filter + strlen(filter), + "(%s=%s)", ref_attrs[i], ndn); + } + strcat(filter, "))"); + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "searching for referrers using filter \"%s\"\n", + filter); + /* Update any matching entry. */ + for (i = 0; + (map_data->bases != NULL) && (map_data->bases[i] != NULL); + i++) { + slapi_search_internal_set_pb(cbdata->pb, + map_data->bases[i], + LDAP_SCOPE_SUB, + filter, + NULL, FALSE, + NULL, + NULL, + state->plugin_identity, + 0); + slapi_search_internal_callback_pb(cbdata->pb, map_data, + NULL, + backend_map_config_entry_set_one_cb, + NULL); + } + free(filter); + } + + /* Allocate the DN we'll use to hold values for comparison. */ referred_to_sdn = slapi_sdn_new(); if (referred_to_sdn == NULL) { slapi_log_error(SLAPI_LOG_PLUGIN, - map_data->state->plugin_desc->spd_id, + state->plugin_desc->spd_id, "error updating entries referred to by %s\n", slapi_entry_get_ndn(cbdata->e)); return TRUE; } - /* For every attribute name which is used to refer to other entries.. */ - referred = cbdata->map_data->referred; - for (i = 0; (referred != NULL) && (referred[i] != NULL); i++) { + /* For every directory entry to which this directory entry refers and + * which also has a corresponding entry in this map, update it. */ + inref_attrs = map_data->inref_attrs; + for (i = 0; (inref_attrs != NULL) && (inref_attrs[i] != NULL); i++) { + /* We're only processing inref attributes for this map. */ + if ((strcmp(inref_attrs[i]->domain, domain) != 0) || + (strcmp(inref_attrs[i]->map, map) != 0)) { + continue; + } + /* Extract the named attribute from the entry. */ values = NULL; - if (slapi_vattr_values_get(cbdata->e, referred[i], &values, - &disposition, &actual_attr, - 0, &buffer_flags) == 0) { - /* For each value of those attributes.. */ - for (j = slapi_valueset_first_value(values, &value); - j != -1; - j = slapi_valueset_next_value(values, j, &value)) { - dn = slapi_value_get_string(value); - if (dn != NULL) { - slapi_sdn_set_dn_byref(referred_to_sdn, - dn); - ndn = slapi_sdn_get_ndn(referred_to_sdn); - /* If the named entry corresponds to an - * entry in this map.. */ - if (map_data_check_entry(map_data->state, - map_data->domain, - map_data->map, - ndn)) { - /* Update it. */ - backend_map_config_entry_set_one_dn(map_data->state, ndn, map_data); - } - } + if (slapi_vattr_values_get(cbdata->e, + inref_attrs[i]->attribute, + &values, &disposition, &actual_attr, + 0, &buffer_flags) != 0) { + continue; + } + /* For each value of this attributes.. */ + for (j = slapi_valueset_first_value(values, &value); + j != -1; + j = slapi_valueset_next_value(values, j, &value)) { + /* Pull out the value, which is a referred-to entry's + * DN. */ + dn = slapi_value_get_string(value); + if (dn == NULL) { + continue; + } + /* Normalize the DN. */ + slapi_sdn_set_dn_byref(referred_to_sdn, dn); + ndn = slapi_sdn_get_ndn(referred_to_sdn); + /* If the named entry corresponds to an entry that's + * already in this map. */ + if (map_data_check_entry(state, domain, map, ndn)) { + /* ...update it. */ + backend_map_config_entry_set_one_dn(state, ndn, + map_data); } - slapi_vattr_values_free(&values, &actual_attr, - buffer_flags); } + slapi_vattr_values_free(&values, &actual_attr, + buffer_flags); } slapi_sdn_free(&referred_to_sdn); return TRUE; } +static void +backend_update_references(struct plugin_state *state, Slapi_Entry *e) +{ + struct backend_update_references_cbdata cbdata; + cbdata.e = e; + cbdata.pb = slapi_pblock_new(); + if (!map_data_foreach_map(state, NULL, + backend_update_references_cb, &cbdata)) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "error updating references for \"%s\"\n", + slapi_entry_get_ndn(cbdata.e)); + } + slapi_pblock_destroy(cbdata.pb); +} + /* Add any map entries which correspond to a directory server entry in this * map. */ @@ -964,7 +1068,6 @@ backend_add_entry_cb(const char *domain, const char *map, void *backend_data, Slapi_Filter *filter; struct backend_map_data *map_data; struct backend_add_entry_cbdata *cbdata; - struct backend_update_referred_to_entries_cbdata rcbdata; map_data = backend_data; cbdata = cbdata_ptr; @@ -972,7 +1075,7 @@ backend_add_entry_cb(const char *domain, const char *map, void *backend_data, /* If the entry doesn't match the map, skip it. */ if (!backend_entry_matches_map(map_data, cbdata->pb, cbdata->e)) { slapi_log_error(SLAPI_LOG_PLUGIN, - map_data->state->plugin_desc->spd_id, + cbdata->state->plugin_desc->spd_id, "entry \"%s\" does not belong in " "\"%s\"/\"%s\"\n", cbdata->ndn, domain, map); @@ -983,19 +1086,6 @@ backend_add_entry_cb(const char *domain, const char *map, void *backend_data, * any that might if this entry doesn't have a key and value. */ backend_map_config_entry_set_one(cbdata->e, map_data); - /* Update entries which need to be updated in case this entry now - * refers to a set of entries. */ - rcbdata.map_data = map_data; - rcbdata.e = cbdata->e; - if (!map_data_foreach_map(cbdata->state, NULL, - backend_update_referred_to_entries_cb, - &rcbdata)) { - slapi_log_error(SLAPI_LOG_PLUGIN, - cbdata->state->plugin_desc->spd_id, - "error updating referred-to entries for " - "\"%s\"\n", cbdata->ndn); - } - return TRUE; } @@ -1041,6 +1131,11 @@ backend_add_cb(Slapi_PBlock *pb) "new entry \"%s\" is a map\n", cbdata.ndn); backend_map_config_entry_add_cb(cbdata.e, cbdata.state); } + + /* Update entries which need to be updated in case this new entry + * refers to them. */ + backend_update_references(cbdata.state, cbdata.e); + map_unlock(); return 0; } @@ -1061,7 +1156,6 @@ backend_modify_entry_cb(const char *domain, const char *map, void *backend_data, Slapi_Filter *filter; struct backend_map_data *map_data; struct backend_modify_entry_cbdata *cbdata; - struct backend_update_referred_to_entries_cbdata rcbdata; map_data = backend_data; cbdata = cbdata_ptr; @@ -1069,25 +1163,13 @@ backend_modify_entry_cb(const char *domain, const char *map, void *backend_data, /* If the entry used to match the map, remove it. */ if (backend_entry_matches_map(map_data, cbdata->pb, cbdata->e_pre)) { slapi_log_error(SLAPI_LOG_PLUGIN, - map_data->state->plugin_desc->spd_id, + cbdata->state->plugin_desc->spd_id, "clearing domain/map/id " "\"%s\"/\"%s\"/(\"%s\")\n", map_data->domain, map_data->map, cbdata->ndn); - map_data_unset_entry_id(map_data->state, + map_data_unset_entry_id(cbdata->state, map_data->domain, map_data->map, cbdata->ndn); - /* Update entries which need to be updated in case this entry - * no longer refers to them. */ - rcbdata.map_data = map_data; - rcbdata.e = cbdata->e_pre; - if (!map_data_foreach_map(cbdata->state, NULL, - backend_update_referred_to_entries_cb, - &rcbdata)) { - slapi_log_error(SLAPI_LOG_PLUGIN, - cbdata->state->plugin_desc->spd_id, - "error updating referred-to entries " - "for \"%s\"\n", cbdata->ndn); - } } /* If the entry now matches the map, add it (or re-add it). */ if (backend_entry_matches_map(map_data, cbdata->pb, cbdata->e_post)) { @@ -1095,18 +1177,6 @@ backend_modify_entry_cb(const char *domain, const char *map, void *backend_data, * clear any that might if this entry doesn't have a key and * value. */ backend_map_config_entry_set_one(cbdata->e_post, map_data); - /* Update entries which need to be updated in case this entry - * no longer refers to them. */ - rcbdata.map_data = map_data; - rcbdata.e = cbdata->e_post; - if (!map_data_foreach_map(cbdata->state, NULL, - backend_update_referred_to_entries_cb, - &rcbdata)) { - slapi_log_error(SLAPI_LOG_PLUGIN, - cbdata->state->plugin_desc->spd_id, - "error updating referred-to entries " - "for \"%s\"\n", cbdata->ndn); - } } return TRUE; } @@ -1146,7 +1216,12 @@ backend_modify_cb(Slapi_PBlock *pb) "error modifying map entries corresponding to " "\"%s\"\n", cbdata.ndn); } - map_unlock(); + /* Update entries which need to be updated in case this entry + * no longer refers to them. */ + backend_update_references(cbdata.state, cbdata.e_pre); + /* Update entries which need to be updated in case this entry + * now refers to them. */ + backend_update_references(cbdata.state, cbdata.e_post); /* If it's a map configuration entry, reconfigure, clear, and * repopulate the map. */ if (backend_entry_is_a_map(cbdata.state, pb, cbdata.e_pre)) { @@ -1163,6 +1238,7 @@ backend_modify_cb(Slapi_PBlock *pb) cbdata.ndn); backend_map_config_entry_add_cb(cbdata.e_post, cbdata.state); } + map_unlock(); return 0; } @@ -1193,12 +1269,12 @@ backend_modrdn_entry_cb(const char *domain, const char *map, void *backend_data, if (matched_pre) { /* If it was a match for the map, clear the entry. */ slapi_log_error(SLAPI_LOG_PLUGIN, - map_data->state->plugin_desc->spd_id, + cbdata->state->plugin_desc->spd_id, "clearing domain/map/id " "\"%s\"/\"%s\"/(\"%s\")\n", map_data->domain, map_data->map, cbdata->ndn_pre); - map_data_unset_entry_id(map_data->state, + map_data_unset_entry_id(cbdata->state, map_data->domain, map_data->map, cbdata->ndn_pre); } @@ -1282,33 +1358,20 @@ backend_delete_entry_cb(const char *domain, const char *map, void *backend_data, { struct backend_map_data *map_data; struct backend_delete_entry_cbdata *cbdata; - struct backend_update_referred_to_entries_cbdata rcbdata; map_data = backend_data; cbdata = cbdata_ptr; /* If it was in the map, remove it. */ if (backend_entry_matches_map(map_data, cbdata->pb, cbdata->e)) { /* Remove this entry from the map. */ slapi_log_error(SLAPI_LOG_PLUGIN, - map_data->state->plugin_desc->spd_id, + cbdata->state->plugin_desc->spd_id, "unsetting domain/map/id" "\"%s\"/\"%s\"=\"%s\"/\"%s\"/(\"%s\")\n", domain, map, map_data->domain, map_data->map, cbdata->ndn); - map_data_unset_entry_id(map_data->state, domain, map, + map_data_unset_entry_id(cbdata->state, domain, map, cbdata->ndn); - /* Update entries which need to be updated in case this entry - * no longer refers to them. */ - rcbdata.map_data = map_data; - rcbdata.e = cbdata->e; - if (!map_data_foreach_map(cbdata->state, NULL, - backend_update_referred_to_entries_cb, - &rcbdata)) { - slapi_log_error(SLAPI_LOG_PLUGIN, - cbdata->state->plugin_desc->spd_id, - "error updating referred-to entries " - "for \"%s\"\n", cbdata->ndn); - } } return TRUE; } @@ -1348,6 +1411,9 @@ backend_delete_cb(Slapi_PBlock *pb) "deleted entry \"%s\" is a map\n", cbdata.ndn); backend_map_config_entry_delete_cb(cbdata.e, cbdata.state); } + /* Update entries which need to be updated in case this entry no longer + * refers to them. */ + backend_update_references(cbdata.state, cbdata.e); map_unlock(); return 0; } |