patch prefixMap

Anatoliy Atanasov anatoliy.atanasov at postpath.com
Mon Jul 21 11:05:57 GMT 2008


Hi Andrew,

I am sending you a patch for updating the prefixMap attribute of the schema when adding new objects and attirbutes to the ldb.

Regards,
Anatoliy


-------------- next part --------------
diff --git a/source/dsdb/schema/schema_init.c b/source/dsdb/schema/schema_init.c
index 71d952b..2ec5ad3 100644
--- a/source/dsdb/schema/schema_init.c
+++ b/source/dsdb/schema/schema_init.c
@@ -268,18 +268,145 @@ WERROR dsdb_verify_oid_mappings_drsuapi(const struct dsdb_schema *schema, const
 
 WERROR dsdb_map_oid2int(const struct dsdb_schema *schema, const char *in, uint32_t *out)
 {
+	return dsdb_find_prefix_for_oid(schema->num_prefixes, schema->prefixes, in, out);
+}
+
+
+WERROR dsdb_map_int2oid(const struct dsdb_schema *schema, uint32_t in, TALLOC_CTX *mem_ctx, const char **out)
+{
 	uint32_t i;
 
 	for (i=0; i < schema->num_prefixes; i++) {
+		const char *val;
+		if (schema->prefixes[i].id != (in & 0xFFFF0000)) {
+			continue;
+		}
+
+		val = talloc_asprintf(mem_ctx, "%s%u",
+				      schema->prefixes[i].oid,
+				      in & 0xFFFF);
+		W_ERROR_HAVE_NO_MEMORY(val);
+
+		*out = val;
+		return WERR_OK;
+	}
+
+	return WERR_DS_NO_MSDS_INTID;
+}
+
+/*
+ * this function is called from within a ldb transaction from the schema_fsmo module
+ */
+WERROR dsdb_create_prefix_mapping(struct ldb_context *ldb, struct dsdb_schema *schema, const char *full_oid)
+{
+	WERROR status;
+	uint32_t num_prefixes;
+	struct dsdb_schema_oid_prefix *prefixes;
+	struct ldb_val ndr_blob;
+	TALLOC_CTX *mem_ctx;
+	uint32_t out;
+
+	mem_ctx = talloc_new(ldb);
+	W_ERROR_HAVE_NO_MEMORY(mem_ctx);
+
+	/* Read prefixes from disk*/
+	status = dsdb_read_prefixes_from_ldb( mem_ctx, ldb, &num_prefixes, &prefixes ); 
+	if (!W_ERROR_IS_OK(status)) {
+		DEBUG(0,("dsdb_create_prefix_mapping: dsdb_read_prefixes_from_ldb failed\n"));
+		talloc_free(mem_ctx);
+		return status;
+	}
+
+	/* Check if there is a prefix for the oid in the prefixes array*/
+	status = dsdb_find_prefix_for_oid( num_prefixes, prefixes, full_oid, &out ); 
+	if (W_ERROR_IS_OK(status)) {
+		/* prefix found*/
+		talloc_free(mem_ctx);
+		return status;
+	}
+	/* Update prefix map in ldb*/
+	/* Update the prefixes */
+	status = dsdb_prefix_map_update(mem_ctx, &num_prefixes, &prefixes, full_oid);
+	if (!W_ERROR_IS_OK(status)) {
+		DEBUG(0,("dsdb_create_prefix_mapping: dsdb_prefix_map_update failed\n"));
+		talloc_free(mem_ctx);
+		return status;
+	}
+	/* Convert prefixes in ndr blob*/
+	status = dsdb_write_prefixes_to_ndr( mem_ctx, ldb, num_prefixes, prefixes, &ndr_blob );
+	if (!W_ERROR_IS_OK(status)) {
+		DEBUG(0,("dsdb_create_prefix_mapping: dsdb_write_prefixes_to_ndr failed\n"));
+		talloc_free(mem_ctx);
+		return status;
+	}
+
+	/* Update prefixMap in ldb*/
+	status = dsdb_write_prefixes_to_ldb( mem_ctx, ldb, &ndr_blob );
+	if (!W_ERROR_IS_OK(status)) {
+		DEBUG(0,("dsdb_create_prefix_mapping: dsdb_write_prefixes_to_ldb failed\n"));
+		talloc_free(mem_ctx);
+		return status;
+	}
+
+	talloc_free(mem_ctx);
+	return status;
+}
+
+WERROR dsdb_prefix_map_update(TALLOC_CTX *mem_ctx, uint32_t *num_prefixes, struct dsdb_schema_oid_prefix **prefixes, const char *oid)
+{
+	uint32_t new_num_prefixes, index_new_prefix, new_entry_id;
+	const char* lastDotOffset;
+	size_t size;
+	
+	new_num_prefixes = *num_prefixes + 1;
+	index_new_prefix = *num_prefixes;
+	new_entry_id = (*num_prefixes)<<16;
+
+	/* Extract the prefix from the oid*/
+	lastDotOffset = strrchr(oid, '.');
+	if (lastDotOffset == NULL) {
+		DEBUG(0,("dsdb_prefix_map_update: failed to find the last dot\n"));
+		return WERR_NOT_FOUND;
+	}
+
+	/* Calculate the size of the remainig string that should be the prefix of it */
+	size = strlen(oid) - strlen(lastDotOffset);
+	if (size <= 0) {
+		DEBUG(0,("dsdb_prefix_map_update: size of the remaining string invalid\n"));
+		return WERR_FOOBAR;
+	}
+	/* Add one because we need to copy the dot */
+	size += 1;
+
+	/* Create a spot in the prefixMap for one more prefix*/
+	(*prefixes) = talloc_realloc(mem_ctx, *prefixes, struct dsdb_schema_oid_prefix, new_num_prefixes);
+	W_ERROR_HAVE_NO_MEMORY(*prefixes);
+
+	/* Add the new prefix entry*/
+	(*prefixes)[index_new_prefix].id = new_entry_id;
+	(*prefixes)[index_new_prefix].oid = talloc_strndup(mem_ctx, oid, size);
+	(*prefixes)[index_new_prefix].oid_len = strlen((*prefixes)[index_new_prefix].oid);
+
+	/* Increase num_prefixes because new prefix has been added */
+	++(*num_prefixes);
+
+	return WERR_OK;
+}
+
+WERROR dsdb_find_prefix_for_oid(uint32_t num_prefixes, const struct dsdb_schema_oid_prefix *prefixes, const char *in, uint32_t *out)
+{
+	uint32_t i;
+
+	for (i=0; i < num_prefixes; i++) {
 		const char *val_str;
 		char *end_str;
 		unsigned val;
 
-		if (strncmp(schema->prefixes[i].oid, in, schema->prefixes[i].oid_len) != 0) {
+		if (strncmp(prefixes[i].oid, in, prefixes[i].oid_len) != 0) {
 			continue;
 		}
 
-		val_str = in + schema->prefixes[i].oid_len;
+		val_str = in + prefixes[i].oid_len;
 		end_str = NULL;
 		errno = 0;
 
@@ -305,58 +432,152 @@ WERROR dsdb_map_oid2int(const struct dsdb_schema *schema, const char *in, uint32
 			return WERR_INVALID_PARAM;
 		}
 
-		*out = schema->prefixes[i].id | val;
+		*out = prefixes[i].id | val;
 		return WERR_OK;
 	}
 
 	return WERR_DS_NO_MSDS_INTID;
 }
 
-WERROR dsdb_map_int2oid(const struct dsdb_schema *schema, uint32_t in, TALLOC_CTX *mem_ctx, const char **out)
+WERROR dsdb_write_prefixes_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, struct ldb_val *ndr_blob)
 {
+	struct ldb_message msg;
+	struct ldb_dn *schema_dn;
+	struct ldb_message_element el;
+	int ret;
+	
+	schema_dn = samdb_schema_dn(ldb);
+	if (!schema_dn) {
+		DEBUG(0,("dsdb_write_prefixes_to_ldb: no schema dn present\n"));	
+		return WERR_FOOBAR;
+	}
+ 
+	el.num_values = 1;
+	el.values = ndr_blob;
+	el.flags = LDB_FLAG_MOD_REPLACE;
+	el.name = talloc_strdup(mem_ctx, "prefixMap");
+ 
+	msg.dn = ldb_dn_copy(mem_ctx, schema_dn);
+	msg.num_elements = 1;
+	msg.elements = &el;
+ 
+	ret = ldb_modify( ldb, &msg );
+	if (ret != 0) {
+		DEBUG(0,("dsdb_write_prefixes_to_ldb: ldb_modify failed\n"));	
+		return WERR_FOOBAR;
+ 	}
+ 
+	return WERR_OK;
+}
+
+WERROR dsdb_read_prefixes_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, uint32_t* num_prefixes, struct dsdb_schema_oid_prefix **prefixes)
+{
+	struct prefixMapBlob *blob;
+	enum ndr_err_code ndr_err;
 	uint32_t i;
+	const struct ldb_val *prefix_val;
+	struct ldb_dn *schema_dn;
+	struct ldb_result *schema_res;
+	int ret;    
+	static const char *schema_attrs[] = {
+		"prefixMap",
+		NULL
+	};
 
-	for (i=0; i < schema->num_prefixes; i++) {
-		const char *val;
-		if (schema->prefixes[i].id != (in & 0xFFFF0000)) {
-			continue;
-		}
+	schema_dn = samdb_schema_dn(ldb);
+	if (!schema_dn) {
+		DEBUG(0,("dsdb_read_prefixes_from_ldb: no schema dn present\n"));
+		return WERR_FOOBAR;
+	}
 
-		val = talloc_asprintf(mem_ctx, "%s%u",
-				      schema->prefixes[i].oid,
-				      in & 0xFFFF);
-		W_ERROR_HAVE_NO_MEMORY(val);
+	ret = ldb_search(ldb, schema_dn, LDB_SCOPE_BASE,NULL, schema_attrs,&schema_res);
+	if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+		DEBUG(0,("dsdb_read_prefixes_from_ldb: no prefix map present\n"));
+		return WERR_FOOBAR;
+	} else if (ret != LDB_SUCCESS) {
+		DEBUG(0,("dsdb_read_prefixes_from_ldb: failed to search the schema head\n"));
+		return WERR_FOOBAR;
+	}
 
-		*out = val;
-		return WERR_OK;
+	prefix_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "prefixMap");
+	if (!prefix_val) {
+		DEBUG(0,("dsdb_read_prefixes_from_ldb: no prefixMap attribute found\n"));
+		return WERR_FOOBAR;
 	}
 
-	return WERR_DS_NO_MSDS_INTID;
+	blob = talloc(mem_ctx, struct prefixMapBlob);
+	W_ERROR_HAVE_NO_MEMORY(blob);
+
+	ndr_err = ndr_pull_struct_blob(prefix_val, blob, 
+					   lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), 
+					   blob,
+					   (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
+	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+		DEBUG(0,("dsdb_read_prefixes_from_ldb: ndr_pull_struct_blob failed\n"));
+		talloc_free(blob);
+		return WERR_FOOBAR;
+	}
+
+	if (blob->version != PREFIX_MAP_VERSION_DSDB) {
+		DEBUG(0,("dsdb_read_prefixes_from_ldb: blob->version incorect\n"));
+		talloc_free(blob);
+		return WERR_FOOBAR;
+	}
+	
+	*num_prefixes = blob->ctr.dsdb.num_mappings;
+	*prefixes = talloc_array(mem_ctx, struct dsdb_schema_oid_prefix, *num_prefixes);
+	if(!(*prefixes)) {
+		talloc_free(blob);
+		return WERR_NOMEM;
+	}
+	for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
+		(*prefixes)[i].id = blob->ctr.dsdb.mappings[i].id_prefix<<16;
+		(*prefixes)[i].oid = talloc_strdup(mem_ctx, blob->ctr.dsdb.mappings[i].oid.oid);
+		(*prefixes)[i].oid = talloc_asprintf_append((*prefixes)[i].oid, "."); 
+		(*prefixes)[i].oid_len = strlen(blob->ctr.dsdb.mappings[i].oid.oid);
+	}
+
+	talloc_free(blob);
+	return WERR_OK;
 }
 
-/*
- * this function is called from within a ldb transaction from the schema_fsmo module
- */
-WERROR dsdb_create_prefix_mapping(struct ldb_context *ldb, struct dsdb_schema *schema, const char *full_oid)
+
+WERROR dsdb_write_prefixes_to_ndr(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, uint32_t num_prefixes, const struct dsdb_schema_oid_prefix *prefixes, struct ldb_val *out)
 {
-	/*
-	 * TODO:
-	 *	- (maybe) read the old prefixMap attribute and parse it
-	 *
-	 *	- recheck the prefix doesn't exist (because the ldb
-	 *	  has maybe a more uptodate value than schem->prefixes
-	 *
-	 *	- calculate a new mapping for the oid prefix of full_oid
-	 *	- store the new prefixMap attribute
-	 *
-	 *	- (maybe) update schema->prefixes
-	 *	or
-	 *	- better find a way to indicate a schema reload,
-	 *	  so that other processes also notice the schema change
-	 */
-	return WERR_NOT_SUPPORTED;
+	struct prefixMapBlob *blob;
+	enum ndr_err_code ndr_err;
+	uint32_t i;
+
+	blob = talloc_zero(mem_ctx, struct prefixMapBlob);
+	W_ERROR_HAVE_NO_MEMORY(blob);
+
+	blob->version = PREFIX_MAP_VERSION_DSDB;
+	blob->ctr.dsdb.num_mappings = num_prefixes;
+	blob->ctr.dsdb.mappings = talloc_realloc(blob,
+											blob->ctr.dsdb.mappings,
+											struct drsuapi_DsReplicaOIDMapping,
+											blob->ctr.dsdb.num_mappings);
+	if (!blob->ctr.dsdb.mappings) {
+		return WERR_NOMEM;
+	}
+
+	for (i=0; i < num_prefixes; i++) {
+		blob->ctr.dsdb.mappings[i].id_prefix = prefixes[i].id>>16;
+		blob->ctr.dsdb.mappings[i].oid.oid = talloc_strdup(blob->ctr.dsdb.mappings, prefixes[i].oid);
+	}
+
+	ndr_err = ndr_push_struct_blob(out, ldb,
+					   lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
+					   blob,
+					   (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
+	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+		return WERR_FOOBAR;
+	}
+	
+	return WERR_OK;
 }
 
+
 #define GET_STRING_LDB(msg, attr, mem_ctx, p, elem, strict) do { \
 	(p)->elem = samdb_result_string(msg, attr, NULL);\
 	if (strict && (p)->elem == NULL) { \


More information about the samba-technical mailing list