discard_const_p(void, schema), (ldb_qsort_cmp_fn_t)replmd_ldb_message_element_attid_sort);
}
+static int replmd_build_la_val(TALLOC_CTX *mem_ctx, struct ldb_val *v, struct dsdb_dn *dsdb_dn,
+ const struct GUID *invocation_id, uint64_t seq_num, time_t t);
+
+/*
+ fix up linked attributes in replmd_add.
+ This involves setting up the right meta-data in extended DN
+ components, and creating backlinks to the object
+ */
+static int replmd_add_fix_la(struct ldb_module *module, struct ldb_message_element *el,
+ uint64_t seq_num, const struct GUID *invocationId, time_t t,
+ struct GUID *guid, const struct dsdb_attribute *sa)
+{
+ int i;
+ TALLOC_CTX *tmp_ctx = talloc_new(el->values);
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+ struct dsdb_schema *schema = dsdb_get_schema(ldb);
+
+ for (i=0; i<el->num_values; i++) {
+ struct ldb_val *v = &el->values[i];
+ struct dsdb_dn *dsdb_dn = dsdb_dn_parse(tmp_ctx, ldb, v, sa->syntax->ldap_oid);
+ struct GUID target_guid;
+ NTSTATUS status;
+ int ret;
+
+ ret = replmd_build_la_val(el->values, v, dsdb_dn, invocationId, seq_num, t);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ /* note that the DN already has the extended
+ components from the extended_dn_store module */
+ status = dsdb_get_extended_dn_guid(dsdb_dn->dn, &target_guid);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(tmp_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ret = replmd_add_backlink(module, schema, guid, &target_guid, true, sa);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+ }
+
+ talloc_free(tmp_ctx);
+ return LDB_SUCCESS;
+}
+
+
+/*
+ intercept add requests
+ */
static int replmd_add(struct ldb_module *module, struct ldb_request *req)
{
struct ldb_context *ldb;
continue;
}
+#if W2K3_LINKED_ATTRIBUTES
+ if (sa->linkID != 0 && dsdb_functional_level(ldb) > DS_DOMAIN_FUNCTION_2000) {
+ ret = replmd_add_fix_la(module, e, ac->seq_num, our_invocation_id, t, &guid, sa);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(ac);
+ return ret;
+ }
+ /* linked attributes are not stored in
+ replPropertyMetaData in FL above w2k */
+ continue;
+ }
+#endif
+
m->attid = sa->attributeID_id;
m->version = 1;
m->originating_change_time = now;
RMD_USN = originating_usn
RMD_VERSION = version
*/
-static int replmd_build_la_val(TALLOC_CTX *mem_ctx, struct ldb_val *v, struct parsed_dn *p,
+static int replmd_build_la_val(TALLOC_CTX *mem_ctx, struct ldb_val *v, struct dsdb_dn *dsdb_dn,
const struct GUID *invocation_id, uint64_t seq_num, time_t t)
{
- struct ldb_dn *dn = p->dsdb_dn->dn;
+ struct ldb_dn *dn = dsdb_dn->dn;
NTTIME now;
const char *tstring, *usn_string;
struct ldb_val tval;
ret = ldb_dn_set_extended_component(dn, "RMD_VERSION", &vers);
if (ret != LDB_SUCCESS) return ret;
- dnstring = dsdb_dn_get_extended_linearized(mem_ctx, p->dsdb_dn, 1);
+ dnstring = dsdb_dn_get_extended_linearized(mem_ctx, dsdb_dn, 1);
if (dnstring == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
}
see replmd_build_la_val for value names
*/
-static int replmd_update_la_val(TALLOC_CTX *mem_ctx, struct ldb_val *v, struct parsed_dn *p,
- struct parsed_dn *old_p, const struct GUID *invocation_id,
+static int replmd_update_la_val(TALLOC_CTX *mem_ctx, struct ldb_val *v, struct dsdb_dn *dsdb_dn,
+ struct dsdb_dn *old_dsdb_dn, const struct GUID *invocation_id,
uint64_t seq_num, time_t t, bool deleted)
{
- struct ldb_dn *dn = p->dsdb_dn->dn;
+ struct ldb_dn *dn = dsdb_dn->dn;
NTTIME now;
const char *tstring, *usn_string;
struct ldb_val tval;
if (ret != LDB_SUCCESS) return ret;
/* get the ADDTIME from the original */
- old_addtime = ldb_dn_get_extended_component(old_p->dsdb_dn->dn, "RMD_ADDTIME");
+ old_addtime = ldb_dn_get_extended_component(old_dsdb_dn->dn, "RMD_ADDTIME");
if (old_addtime == NULL) {
old_addtime = &tval;
}
- if (p != old_p) {
+ if (dsdb_dn != old_dsdb_dn) {
ret = ldb_dn_set_extended_component(dn, "RMD_ADDTIME", old_addtime);
if (ret != LDB_SUCCESS) return ret;
}
if (ret != LDB_SUCCESS) return ret;
/* increase the version by 1 */
- old_version = ldb_dn_get_extended_component(old_p->dsdb_dn->dn, "RMD_VERSION");
+ old_version = ldb_dn_get_extended_component(old_dsdb_dn->dn, "RMD_VERSION");
if (old_version == NULL) {
vers = data_blob_string_const("0");
} else {
ret = ldb_dn_set_extended_component(dn, "RMD_VERSION", &vers);
if (ret != LDB_SUCCESS) return ret;
- dnstring = dsdb_dn_get_extended_linearized(mem_ctx, p->dsdb_dn, 1);
+ dnstring = dsdb_dn_get_extended_linearized(mem_ctx, dsdb_dn, 1);
if (dnstring == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
}
talloc_free(tmp_ctx);
return LDB_ERR_OPERATIONS_ERROR;
}
- ret = replmd_build_la_val(new_values, &new_values[num_new_values], &dns[i],
+ ret = replmd_build_la_val(new_values, &new_values[num_new_values], dns[i].dsdb_dn,
invocation_id, seq_num, t);
if (ret != LDB_SUCCESS) {
talloc_free(tmp_ctx);
talloc_free(tmp_ctx);
return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
}
- ret = replmd_update_la_val(old_el->values, p->v, &dns[i], p, invocation_id, seq_num, t, false);
+ ret = replmd_update_la_val(old_el->values, p->v, dns[i].dsdb_dn, p->dsdb_dn,
+ invocation_id, seq_num, t, false);
if (ret != LDB_SUCCESS) {
talloc_free(tmp_ctx);
return ret;
v = ldb_dn_get_extended_component(p->dsdb_dn->dn, "DELETED");
if (v != NULL) continue;
- ret = replmd_update_la_val(old_el->values, p->v, p, p, invocation_id, seq_num, t, true);
+ ret = replmd_update_la_val(old_el->values, p->v, p->dsdb_dn, p->dsdb_dn,
+ invocation_id, seq_num, t, true);
if (ret != LDB_SUCCESS) {
talloc_free(tmp_ctx);
return ret;
continue;
}
- ret = replmd_update_la_val(old_el->values, old_p->v, old_p, old_p,
+ ret = replmd_update_la_val(old_el->values, old_p->v, old_p->dsdb_dn, old_p->dsdb_dn,
invocation_id, seq_num, t, true);
if (ret != LDB_SUCCESS) {
talloc_free(tmp_ctx);
(old_p = parsed_dn_find(old_dns,
old_num_values, p->guid)) != NULL) {
/* update in place */
- ret = replmd_update_la_val(old_el->values, old_p->v, old_p,
- old_p, invocation_id,
+ ret = replmd_update_la_val(old_el->values, old_p->v, old_p->dsdb_dn,
+ old_p->dsdb_dn, invocation_id,
seq_num, t, false);
if (ret != LDB_SUCCESS) {
talloc_free(tmp_ctx);
talloc_free(tmp_ctx);
return LDB_ERR_OPERATIONS_ERROR;
}
- ret = replmd_build_la_val(new_values, &new_values[num_new_values], &dns[i],
+ ret = replmd_build_la_val(new_values, &new_values[num_new_values], dns[i].dsdb_dn,
invocation_id, seq_num, t);
if (ret != LDB_SUCCESS) {
talloc_free(tmp_ctx);
for (i=0; i<el->num_values; i++) {
struct dsdb_dn *dsdb_dn;
- const struct ldb_val *v;
NTSTATUS status;
int ret;
struct GUID guid2;
return LDB_ERR_OPERATIONS_ERROR;
}
- v = ldb_dn_get_extended_component(dsdb_dn->dn, "GUID");
- if (!v) {
- talloc_free(tmp_ctx);
- return LDB_ERR_OPERATIONS_ERROR;
- }
- status = GUID_from_ndr_blob(v, &guid2);
+ status = dsdb_get_extended_dn_guid(dsdb_dn->dn, &guid2);
if (!NT_STATUS_IS_OK(status)) {
talloc_free(tmp_ctx);
return LDB_ERR_OPERATIONS_ERROR;