Hello,

This is all we need for RecordGenerator and IPA locations.
Design: https://fedorahosted.org/bind-dyndb-ldap/wiki/Design/RecordGenerator

https://fedorahosted.org/bind-dyndb-ldap/ticket/126


Limitation is that all the changes are applied only on BIND reload. I will
think about eliminating this requirement but it is not that easy.

-- 
Petr^2 Spacek
From 2c2c81b107c6bb413d7ae9b353de12d5f893cbfe Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Thu, 9 Jun 2016 09:26:56 +0200
Subject: [PATCH] Read idnsSubstitutionVariable;ipalocation variable from
 server's config in LDAP.

This is just a quick hack to unblock implementation of RecordGenerator
feature. Only supported variable name is "ipalocation".

Handling of idnsSubstitutionVariable should be generalized so it can accept
any valid variable name. Unfortunatelly it will require rework of
settings system and we do not have time for it right now.

Design: https://fedorahosted.org/bind-dyndb-ldap/wiki/Design/RecordGenerator

https://fedorahosted.org/bind-dyndb-ldap/ticket/126
---
 src/ldap_helper.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/src/ldap_helper.c b/src/ldap_helper.c
index da19cb15e00d2406fc13a35aefd1853fe2fb6d34..f4776d1d6f0ce4649974518893bc24954353f9b3 100644
--- a/src/ldap_helper.c
+++ b/src/ldap_helper.c
@@ -263,6 +263,7 @@ static setting_t settings_server_ldap_default[] = {
 	{ "fake_mname",		no_default_string	},
 	{ "forwarders",		no_default_string	},
 	{ "forward_policy",	no_default_string	},
+	{ "substitutionvariable_ipalocation",	no_default_string	},
 	end_of_settings
 };
 
@@ -626,8 +627,6 @@ new_ldap_instance(isc_mem_t *mctx, const char *db_name,
 	CHECK(settings_set_create(mctx, settings_server_ldap_default,
 	      sizeof(settings_server_ldap_default), settings_name,
 	      ldap_inst->global_settings, &ldap_inst->server_ldap_settings));
-	if (settings_set_isfilled(ldap_inst->server_ldap_settings) != ISC_TRUE)
-		CLEANUP_WITH(ISC_R_FAILURE);
 
 	ldap_inst->empty_fwdz_settings = (settings_set_t) {
 			NULL,
@@ -1466,6 +1465,13 @@ ldap_parse_serverconfigentry(ldap_entry_t *entry, ldap_instance_t *inst)
 	if (result != ISC_R_SUCCESS && result != ISC_R_IGNORE)
 		goto cleanup;
 
+	result = setting_update_from_ldap_entry("substitutionvariable_ipalocation",
+						inst->server_ldap_settings,
+						"idnsSubstitutionVariable;ipalocation",
+						entry);
+	if (result != ISC_R_SUCCESS && result != ISC_R_IGNORE)
+		goto cleanup;
+
 cleanup:
 	/* Configuration errors are not fatal. */
 	/* TODO: log something? */
-- 
2.5.5

From 794008201fa9661af0093a9fc645203d912e2d33 Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Fri, 10 Jun 2016 17:28:42 +0200
Subject: [PATCH] Refactor ldap_parse_rrentry to make settings system available
 to it.

This will be handy for record generator.

https://fedorahosted.org/bind-dyndb-ldap/ticket/126
---
 src/ldap_helper.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/src/ldap_helper.c b/src/ldap_helper.c
index f4776d1d6f0ce4649974518893bc24954353f9b3..0fada6ea11f32a1687513e605d766b12166b7c63 100644
--- a/src/ldap_helper.c
+++ b/src/ldap_helper.c
@@ -297,9 +297,11 @@ ldap_parse_master_zoneentry(ldap_entry_t * const entry, dns_db_t * const olddb,
 			    ldap_instance_t *const inst,
 			    isc_task_t *const task)
 			    ATTR_NONNULL(1,3,4) ATTR_CHECKRESULT;
+
 static isc_result_t
 ldap_parse_rrentry(isc_mem_t *mctx, ldap_entry_t *entry, dns_name_t *origin,
-		   const char *fake_mname, ldapdb_rdatalist_t *rdatalist) ATTR_NONNULLS ATTR_CHECKRESULT;
+		   const settings_set_t * const settings,
+		   ldapdb_rdatalist_t *rdatalist) ATTR_NONNULLS ATTR_CHECKRESULT;
 
 static isc_result_t ldap_connect(ldap_instance_t *ldap_inst,
 		ldap_connection_t *ldap_conn, isc_boolean_t force) ATTR_NONNULLS ATTR_CHECKRESULT;
@@ -1891,7 +1893,6 @@ zone_sync_apex(const ldap_instance_t * const inst,
 	       isc_boolean_t * const ldap_writeback,
 	       isc_boolean_t * const data_changed) {
 	isc_result_t result;
-	const char *fake_mname = NULL;
 	ldapdb_rdatalist_t rdatalist;
 	dns_rdatasetiter_t *rbt_rds_iterator = NULL;
 	/* RBTDB's origin node cannot be detached until the node is non-empty.
@@ -1905,10 +1906,8 @@ zone_sync_apex(const ldap_instance_t * const inst,
 	INIT_LIST(rdatalist);
 	*ldap_writeback = ISC_FALSE; /* GCC */
 
-	CHECK(setting_get_str("fake_mname", inst->server_ldap_settings,
-			      &fake_mname));
-	CHECK(ldap_parse_rrentry(inst->mctx, entry, &name, fake_mname,
-				 &rdatalist));
+	CHECK(ldap_parse_rrentry(inst->mctx, entry, &name,
+				 inst->server_ldap_settings, &rdatalist));
 
 	CHECK(dns_db_getoriginnode(rbtdb, &node));
 	result = dns_db_allrdatasets(rbtdb, node, version, 0,
@@ -2292,7 +2291,8 @@ free_rdatalist(isc_mem_t *mctx, dns_rdatalist_t *rdlist)
  */
 static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT
 ldap_parse_rrentry(isc_mem_t *mctx, ldap_entry_t *entry, dns_name_t *origin,
-		   const char *fake_mname, ldapdb_rdatalist_t *rdatalist)
+		   const settings_set_t * const settings,
+		   ldapdb_rdatalist_t *rdatalist)
 {
 	isc_result_t result;
 	dns_rdataclass_t rdclass;
@@ -2303,12 +2303,15 @@ ldap_parse_rrentry(isc_mem_t *mctx, ldap_entry_t *entry, dns_name_t *origin,
 	ldap_attribute_t *attr;
 	const char *data_str = "<NULL data>";
 	ld_string_t *data_buf = NULL;
+	const char *fake_mname;
 
 	REQUIRE(EMPTY(*rdatalist));
 
 	CHECK(str_new(mctx, &data_buf));
-	if ((entry->class & LDAP_ENTRYCLASS_MASTER) != 0)
+	if ((entry->class & LDAP_ENTRYCLASS_MASTER) != 0) {
+		CHECK(setting_get_str("fake_mname", settings, &fake_mname));
 		CHECK(add_soa_record(mctx, origin, entry, rdatalist, fake_mname));
+	}
 
 	rdclass = ldap_entry_getrdclass(entry);
 	ttl = ldap_entry_getttl(entry);
@@ -3593,7 +3596,6 @@ update_record(isc_task_t *task, isc_event_t *event)
 	isc_boolean_t zone_reloaded = ISC_FALSE;
 	isc_uint32_t serial;
 	ldap_entry_t *entry = pevent->entry;
-	const char *fake_mname = NULL;
 
 	dns_db_t *rbtdb = NULL;
 	dns_db_t *ldapdb = NULL;
@@ -3681,10 +3683,8 @@ update_restart:
 		/* Parse new data from LDAP. */
 		log_debug(5, "syncrepl_update: updating name in rbtdb, "
 			  "%s", ldap_entry_logname(entry));
-		CHECK(setting_get_str("fake_mname", inst->server_ldap_settings,
-				      &fake_mname));
-		CHECK(ldap_parse_rrentry(mctx, entry, &entry->zone_name, fake_mname,
-					 &rdatalist));
+		CHECK(ldap_parse_rrentry(mctx, entry, &entry->zone_name,
+					 inst->server_ldap_settings, &rdatalist));
 	}
 
 	if (rbt_rds_iterator != NULL) {
-- 
2.5.5

From ff1c53bf08fb2248e31b72df84a5a0ccd29e2b9e Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Sat, 11 Jun 2016 16:56:29 +0200
Subject: [PATCH] Revive str.c:str_cat_char_len function from git history.

This previously unused function was removed in
6c212c81f1297bef844cf4c6d6f36fc8231e4a45.

It will be handy for implementation of record generator.

https://fedorahosted.org/bind-dyndb-ldap/ticket/126
---
 src/str.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/src/str.c b/src/str.c
index 46ec73f6fe909a4f1b98d8f7387ddee83e82f95f..6797eded04f22a5ad1dc2c0628779ef916983e5b 100644
--- a/src/str.c
+++ b/src/str.c
@@ -263,6 +263,34 @@ cleanup:
 	return result;
 }
 
+/**
+ * Append len bytes from src to dest.
+ */
+isc_result_t
+str_cat_char_len(ld_string_t *dest, const char *src, size_t len)
+{
+       isc_result_t result;
+       char *from;
+       size_t dest_size;
+
+       REQUIRE(dest != NULL);
+
+        if (src == NULL || len == 0)
+            return ISC_R_SUCCESS;
+
+       dest_size = str_len_internal(dest);
+
+       CHECK(str_alloc(dest, dest_size + len));
+       from = dest->data + dest_size;
+       memcpy(from, src, len);
+       from[len] = '\0';
+
+       return ISC_R_SUCCESS;
+
+cleanup:
+       return result;
+}
+
 /*
  * A sprintf() like function.
  */
-- 
2.5.5

From ff0e3f0864c521465b6f16304ab5b7ce45a7d5db Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Sat, 11 Jun 2016 16:58:01 +0200
Subject: [PATCH] Support dynamic record generation using
 idnsTemplateAttribute.

This feature allows bind-dyndb-ldap instance to generate records using
user-provided template and variables from bind-dyndb-ldap's configuration.

idnsAttributeTemplate defines template which is used for dynamic record
generation. Generated values take precedence over all statically defined
attributes with RRs. All static RRs are ignored if substitution was successful.

Limitations:
- Substitution currently works only for *Record attributes
  and cannot be used for anything else.
- idnsAttributeTemplate works only on idnsRecord objects and does not
  work on zones or configs.

Design: https://fedorahosted.org/bind-dyndb-ldap/wiki/Design/RecordGenerator

https://fedorahosted.org/bind-dyndb-ldap/ticket/126
---
 doc/schema.ldif   |  10 ++-
 src/ldap_helper.c | 197 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 204 insertions(+), 3 deletions(-)

diff --git a/doc/schema.ldif b/doc/schema.ldif
index d687b5ceb48b27aee36a8c74d4c5a67f00d667db..de0702efc9c0a208ae476c67e993f6a7f8741847 100644
--- a/doc/schema.ldif
+++ b/doc/schema.ldif
@@ -358,6 +358,12 @@ attributeTypes: ( 2.16.840.1.113730.3.8.5.31
  EQUALITY caseIgnoreMatch
  SINGLE-VALUE )
 #
+attributeTypes: ( 2.16.840.1.113730.3.8.5.30 
+ NAME 'idnsSubstitutionVariable' 
+ DESC 'User defined variable for DNS plugin' 
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 
+ EQUALITY caseIgnoreIA5Match )
+#
 objectClasses: ( 2.16.840.1.113730.3.8.6.0 
  NAME 'idnsRecord' 
  DESC 'dns Record, usually a host' 
@@ -406,4 +412,6 @@ objectClasses: ( 2.16.840.1.113730.3.8.6.6
  SUP top 
  STRUCTURAL 
  MUST ( idnsServerId ) 
- MAY ( idnsSOAmName $ idnsForwarders $ idnsForwardPolicy ) )
+ MAY ( idnsSOAmName $ idnsForwarders $ idnsForwardPolicy $ 
+       idnsSubstitutionVariable 
+     ) )
diff --git a/src/ldap_helper.c b/src/ldap_helper.c
index 0fada6ea11f32a1687513e605d766b12166b7c63..09cc5a6ffd117dda0971dde7bdfcd2e9beb7832a 100644
--- a/src/ldap_helper.c
+++ b/src/ldap_helper.c
@@ -47,6 +47,7 @@
 #define LDAP_DEPRECATED 1
 #include <ldap.h>
 #include <limits.h>
+#include <regex.h>
 #include <sasl/sasl.h>
 #include <signal.h>
 #include <stddef.h>
@@ -2286,8 +2287,192 @@ free_rdatalist(isc_mem_t *mctx, dns_rdatalist_t *rdlist)
 		SAFE_MEM_PUT_PTR(mctx, rdata);
 	}
 }
+
 /**
- * @param rdatalist[in,out] Has to be empty initialized list.
+ * Replace occurrences of \{variable_name\} with respective strings from
+ * settings tree. Remaining parts of the original string are just copied
+ * into the output.
+ *
+ * Double-escaped strings \\{ \\} do not trigger substitution.
+ * Nested references will expand only innermost variable: \{\{var1\}\}
+ * Non-matching parentheses and other garbage will be copied verbatim
+ * without trigerring an error.
+ *
+ * @retval  ISC_R_SUCCESS  Output string is valid. Caller must deallocate output.
+ * @retval  ISC_R_IGNORE   Some variables used in the template are not defined
+ *                         in settings tree. Substitution was terminated
+ *                         prematurely and output is not available.
+ * @retval  others         Unexpected errors.
+ */
+static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT
+ldap_substitute_rr_template(isc_mem_t *mctx, const settings_set_t const * set,
+			    ld_string_t *orig_val, ld_string_t **output) {
+	isc_result_t result;
+	regex_t regex;
+	regmatch_t matches[3];
+	size_t processed = 0;
+	char *tmp = NULL;
+	const char *setting_name;
+	setting_t *setting;
+	ld_string_t *replaced = NULL;
+
+	/* match \{variable_name\} in the text
+	 * \{ and \} must not be double-escaped like \\{ or \\} */
+	if (regcomp(&regex,
+		    "\\(^\\|[^\\]\\)" /* character preceding \{ = matches[1] */
+		    "\\\\{"
+		    "\\([a-zA-Z0-9_-]\\+\\)" /* variable name = matches[2] */
+		    "\\\\}",
+		    0) != 0)
+		CLEANUP_WITH(ISC_R_UNEXPECTED);
+
+	CHECK(str_new(mctx, &replaced));
+	CHECKED_MEM_STRDUP(mctx, str_buf(orig_val), tmp);
+
+	while (regexec(&regex, tmp + processed,
+		       sizeof(matches)/sizeof(regmatch_t),
+		       matches, 0) == 0)
+	{
+		/* derelativize offsets to make sure they
+		 * always start from tmp instead of tmp + processed */
+		for (size_t i = 0; i < sizeof(matches)/sizeof(regmatch_t); i++) {
+			matches[i].rm_so += processed;
+			matches[i].rm_eo += processed;
+		}
+		/* copy verbatim part of the string which precedes the \{ */
+		CHECK(str_cat_char_len(replaced,
+				       tmp + processed,
+				       matches[1].rm_eo - processed));
+
+		/* find value for given variable name in settings tree */
+		setting_name = tmp + matches[2].rm_so;
+		tmp[matches[2].rm_eo] = '\0';
+		setting = NULL;
+		result = setting_find(setting_name, set, isc_boolean_true,
+				      isc_boolean_true, &setting);
+		if (result != ISC_R_SUCCESS) {
+			log_debug(3, "setting '%s' is not defined so it "
+				  "cannot be substituted into template '%s'",
+				  setting_name, str_buf(orig_val));
+			CLEANUP_WITH(ISC_R_IGNORE);
+		}
+		if (setting->type != ST_STRING) {
+			log_bug("setting '%s' it not string so it cannot be "
+				"substituted", setting_name);
+			CLEANUP_WITH(ISC_R_NOTIMPLEMENTED);
+		}
+		CHECK(str_cat_char(replaced, setting->value.value_char));
+
+		/* end offset of previous match = matches[0].rm_eo */
+		processed = matches[0].rm_eo;
+	};
+
+	/* copy remaining part of the string */
+	CHECK(str_cat_char(replaced, tmp + processed));
+
+	*output = replaced;
+	replaced = NULL;
+	result = ISC_R_SUCCESS;
+
+cleanup:
+	if (tmp != NULL)
+		isc_mem_free(mctx, tmp);
+
+	str_destroy(&replaced);
+	return result;
+}
+
+/**
+ * Substitute strings into idnsTemplateAttributes
+ * and parse results into list of rdatas.
+ *
+ * idnsTemplateAttribute must have exactly one sub-type like "TXTRecord"
+ * (e.g. "idnsTemplateAttribute;TXTRecord"). The sub-type specifies target type.
+ *
+ * @warning Substitution currently works only for *Record attributes
+ *          and cannot be used for anything else.
+ *
+ * @retval  ISC_R_SUCCESS  A template exists in the entry and values
+ *                         were successfully substituted into it.
+ *                         Rdatalist contains new rdata.
+ * @retval  ISC_R_IGNORE   No template was found or variables
+ *                         do not have defined values. Ignore output.
+ */
+static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT
+ldap_parse_rrentry_template(isc_mem_t *mctx, ldap_entry_t *entry,
+			    dns_name_t *origin,
+			    const settings_set_t * const settings,
+			    ldapdb_rdatalist_t *rdatalist)
+{
+	isc_result_t result;
+	ldap_attribute_t *attr;
+	ld_string_t *orig_val = NULL;
+	ld_string_t *new_val = NULL;
+	dns_rdata_t *rdata = NULL;
+	dns_rdataclass_t rdclass;
+	dns_ttl_t ttl;
+	dns_rdatatype_t rdtype;
+	dns_rdatalist_t *rdlist = NULL;
+	isc_boolean_t did_something = ISC_FALSE;
+	static const char prefix[] = "idnsTemplateAttribute;";
+	static const char prefix_len = sizeof(prefix) - 1;
+
+	CHECK(str_new(mctx, &orig_val));
+	rdclass = ldap_entry_getrdclass(entry);
+	ttl = ldap_entry_getttl(entry);
+
+	while ((attr = ldap_entry_nextattr(entry)) != NULL) {
+		if (strncasecmp(prefix, attr->name, prefix_len) != 0)
+			continue;
+
+		result = ldap_attribute_to_rdatatype(attr->name + prefix_len,
+						     &rdtype);
+		if (result != ISC_R_SUCCESS) {
+			log_bug("%s: substitution into '%s' is not supported",
+				ldap_entry_logname(entry),
+				attr->name + prefix_len);
+			continue;
+		}
+
+		CHECK(findrdatatype_or_create(mctx, rdatalist, rdclass,
+					      rdtype, ttl, &rdlist));
+		for (result = ldap_attr_firstvalue(attr, orig_val);
+		     result == ISC_R_SUCCESS;
+		     result = ldap_attr_nextvalue(attr, orig_val)) {
+			str_destroy(&new_val);
+			CHECK(ldap_substitute_rr_template(mctx, settings,
+							  orig_val, &new_val));
+			log_debug(10, "%s: substituted '%s' '%s' -> '%s'",
+				  ldap_entry_logname(entry), attr->name,
+				  str_buf(orig_val), str_buf(new_val));
+			CHECK(parse_rdata(mctx, entry, rdclass, rdtype, origin,
+					  str_buf(new_val), &rdata));
+			APPEND(rdlist->rdata, rdata, link);
+			rdata = NULL;
+			did_something = ISC_TRUE;
+		}
+	}
+
+cleanup:
+	str_destroy(&orig_val);
+	str_destroy(&new_val);
+	if (result == ISC_R_NOMORE || result == ISC_R_SUCCESS)
+		result = did_something ? ISC_R_SUCCESS : ISC_R_IGNORE;
+
+	return result;
+}
+
+/**
+ * Parse object containing DNS records and substitute idnsAttributeTemplates
+ * into it if they are defined.
+ *
+ * idnsAttributeTemplates take precedence over all statically defined
+ * attributes with RRs.
+ * All static RRs are ignored if substitution was successful.
+ *
+ * @pre rdatalist is empty initialized list.
+ *
+ * @param rdatalist[in,out]
  */
 static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT
 ldap_parse_rrentry(isc_mem_t *mctx, ldap_entry_t *entry, dns_name_t *origin,
@@ -2307,15 +2492,23 @@ ldap_parse_rrentry(isc_mem_t *mctx, ldap_entry_t *entry, dns_name_t *origin,
 
 	REQUIRE(EMPTY(*rdatalist));
 
-	CHECK(str_new(mctx, &data_buf));
 	if ((entry->class & LDAP_ENTRYCLASS_MASTER) != 0) {
 		CHECK(setting_get_str("fake_mname", settings, &fake_mname));
 		CHECK(add_soa_record(mctx, origin, entry, rdatalist, fake_mname));
 	}
 
 	rdclass = ldap_entry_getrdclass(entry);
 	ttl = ldap_entry_getttl(entry);
 
+	result = ldap_parse_rrentry_template(mctx, entry, origin, settings,
+					     rdatalist);
+	if (result == ISC_R_SUCCESS)
+		/* successful substitution overrides all constants */
+		return result;
+	else if (result != ISC_R_IGNORE)
+		goto cleanup;
+
+	CHECK(str_new(mctx, &data_buf));
 	for (result = ldap_entry_firstrdtype(entry, &attr, &rdtype);
 	     result == ISC_R_SUCCESS;
 	     result = ldap_entry_nextrdtype(entry, &attr, &rdtype)) {
-- 
2.5.5

From 89ae2ee0c0d723a9f8b8d9ef18e8ea2ee95b6ee6 Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Sat, 11 Jun 2016 19:06:25 +0200
Subject: [PATCH] Detect unsupported combination of idnsTemplateObject with
 other object classes.

https://fedorahosted.org/bind-dyndb-ldap/ticket/126
---
 src/ldap_entry.c | 11 +++++++++++
 src/ldap_entry.h |  1 +
 2 files changed, 12 insertions(+)

diff --git a/src/ldap_entry.c b/src/ldap_entry.c
index a2d8a834cd4f3ca35bcb55cf90043d0aa0ef18e6..8f19b0b384699129ee641e7c316a16a5b1779fb7 100644
--- a/src/ldap_entry.c
+++ b/src/ldap_entry.c
@@ -221,6 +221,12 @@ ldap_entry_parse(isc_mem_t *mctx, LDAP *ld, LDAPMessage *ldap_entry,
 	}
 	entry->uuid = ber_dupbv(NULL, uuid);
 	CHECK(ldap_entry_parseclass(entry, &entry->class));
+	if ((entry->class & LDAP_ENTRYCLASS_TEMPLATE) != 0
+	    && (entry->class
+		& ~(LDAP_ENTRYCLASS_TEMPLATE | LDAP_ENTRYCLASS_RR)) != 0) {
+		log_bug("idnsTemplateObject is not supported with anything "
+			"else than idnsRecord: %s", ldap_entry_logname(entry));
+	}
 
 	if ((entry->class &
 	    (LDAP_ENTRYCLASS_MASTER | LDAP_ENTRYCLASS_FORWARD
@@ -444,6 +450,8 @@ ldap_entry_parseclass(ldap_entry_t *entry, ldap_entryclass_t *class)
 	for (val = HEAD(values); val != NULL; val = NEXT(val, link)) {
 		if (!strcasecmp(val->value, "idnsrecord"))
 			entryclass |= LDAP_ENTRYCLASS_RR;
+		else if (!strcasecmp(val->value, "idnsTemplateObject"))
+			entryclass |= LDAP_ENTRYCLASS_TEMPLATE;
 		else if (!strcasecmp(val->value, "idnszone"))
 			entryclass |= LDAP_ENTRYCLASS_MASTER;
 		else if (!strcasecmp(val->value, "idnsforwardzone"))
@@ -549,6 +557,9 @@ ldap_entry_getclassname(const ldap_entryclass_t class) {
 		return "config object";
 	else if ((class & LDAP_ENTRYCLASS_SERVERCONFIG) != 0)
 		return "server config object";
+	else if ((class & LDAP_ENTRYCLASS_RR) != 0
+		 && (class & LDAP_ENTRYCLASS_TEMPLATE) != 0)
+		return "resource record template";
 	else if ((class & LDAP_ENTRYCLASS_RR) != 0)
 		return "resource record";
 	else if (class != 0)
diff --git a/src/ldap_entry.h b/src/ldap_entry.h
index 50e725aa4f2f6bf8420b95c6ee451e238fad9f27..357aa9f3e24e37094799ba044e1884c9d65e1178 100644
--- a/src/ldap_entry.h
+++ b/src/ldap_entry.h
@@ -68,6 +68,7 @@ struct ldap_attribute {
 #define LDAP_ENTRYCLASS_CONFIG	0x4
 #define LDAP_ENTRYCLASS_FORWARD	0x8
 #define LDAP_ENTRYCLASS_SERVERCONFIG	0x10
+#define LDAP_ENTRYCLASS_TEMPLATE	0x20
 
 #define DEFAULT_TTL 86400
 
-- 
2.5.5

From 13eec48ae597c460445944ae08c4598158996788 Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Sat, 11 Jun 2016 19:11:20 +0200
Subject: [PATCH] Optimize idnsTemplateAttribute processing.

Is is not necessary to call idnsTemplateAttribute machinery when
idnsTemplateObject object class is not present.

https://fedorahosted.org/bind-dyndb-ldap/ticket/126
---
 src/ldap_helper.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/src/ldap_helper.c b/src/ldap_helper.c
index 09cc5a6ffd117dda0971dde7bdfcd2e9beb7832a..663f07392594c3947453c2fc011f8429f986f7bd 100644
--- a/src/ldap_helper.c
+++ b/src/ldap_helper.c
@@ -2500,13 +2500,15 @@ ldap_parse_rrentry(isc_mem_t *mctx, ldap_entry_t *entry, dns_name_t *origin,
 	rdclass = ldap_entry_getrdclass(entry);
 	ttl = ldap_entry_getttl(entry);
 
-	result = ldap_parse_rrentry_template(mctx, entry, origin, settings,
-					     rdatalist);
-	if (result == ISC_R_SUCCESS)
-		/* successful substitution overrides all constants */
-		return result;
-	else if (result != ISC_R_IGNORE)
-		goto cleanup;
+	if ((entry->class & LDAP_ENTRYCLASS_TEMPLATE) != 0) {
+		result = ldap_parse_rrentry_template(mctx, entry, origin,
+						     settings, rdatalist);
+		if (result == ISC_R_SUCCESS)
+			/* successful substitution overrides all constants */
+			return result;
+		else if (result != ISC_R_IGNORE)
+			goto cleanup;
+	}
 
 	CHECK(str_new(mctx, &data_buf));
 	for (result = ldap_entry_firstrdtype(entry, &attr, &rdtype);
-- 
2.5.5

-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to