Hello,
this patch is first proof-of-concept implementation of
https://fedorahosted.org/bind-dyndb-ldap/ticket/67: Implement SOA serial
number increments for external changes.
No optimizations are inside. SOA serial is bumped for each record after each
restart, changes in root records are not handled and so on. It is really
proof-of-concept.
It uses unix timestamp for "local" SOA serials to improve situation with local
serials. Unix timestamps should not go to far future as YEAR-MONTH-DAY serials.
Please, let me know if you see some "principle" problems.
Thanks.
Petr^2 Spacek
From c14eedd35682185702f58c3f6eaabb0237f38b15 Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Wed, 27 Jun 2012 10:36:26 +0200
Subject: [PATCH] SOA autoincrement feature Signed-off-by: Petr Spacek
<pspa...@redhat.com>
---
src/ldap_helper.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 71 insertions(+), 1 deletions(-)
diff --git a/src/ldap_helper.c b/src/ldap_helper.c
index 7f0a6f4b37171a6fa4db79cd32fdd8bc62288e0f..ff84ff7256a352f776b31dd221d291234eaabae7 100644
--- a/src/ldap_helper.c
+++ b/src/ldap_helper.c
@@ -34,6 +34,7 @@
#include <dns/zt.h>
#include <dns/byaddr.h>
#include <dns/forward.h>
+#include <dns/soa.h>
#include <isc/buffer.h>
#include <isc/lex.h>
@@ -172,6 +173,7 @@ struct ldap_instance {
isc_boolean_t exiting;
isc_boolean_t sync_ptr;
isc_boolean_t dyn_update;
+ isc_boolean_t soa_autoincrement;
};
struct ldap_pool {
@@ -343,6 +345,7 @@ new_ldap_instance(isc_mem_t *mctx, const char *db_name,
{ "ldap_hostname", default_string("") },
{ "sync_ptr", default_boolean(ISC_FALSE) },
{ "dyn_update", default_boolean(ISC_FALSE) },
+ { "serial_autoincrement", default_boolean(ISC_FALSE) },
end_of_settings
};
@@ -401,6 +404,7 @@ new_ldap_instance(isc_mem_t *mctx, const char *db_name,
ldap_settings[i++].target = ldap_inst->ldap_hostname;
ldap_settings[i++].target = &ldap_inst->sync_ptr;
ldap_settings[i++].target = &ldap_inst->dyn_update;
+ ldap_settings[i++].target = &ldap_inst->soa_autoincrement;
CHECK(set_settings(ldap_settings, argv));
/* Set timer for deadlock detection inside semaphore_wait_timed . */
@@ -463,6 +467,13 @@ new_ldap_instance(isc_mem_t *mctx, const char *db_name,
"increasing limit");
ldap_inst->connections = 3;
}
+ if (ldap_inst->soa_autoincrement == ISC_TRUE
+ && ldap_inst->psearch != ISC_TRUE) {
+ log_error("SOA serial number auto-increment feature requires "
+ "persistent search");
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
CHECK(new_ldap_cache(mctx, argv, &ldap_inst->cache, ldap_inst->psearch));
CHECK(ldap_pool_create(mctx, ldap_inst->connections, &ldap_inst->pool));
@@ -2741,6 +2752,60 @@ ldap_pscontrol_destroy(isc_mem_t *mctx, LDAPControl **ctrlp)
*ctrlp = NULL;
}
+isc_result_t
+increment_soa_serial(isc_mem_t *mctx, ldap_instance_t *inst, dns_name_t *zone_name) {
+ isc_result_t result = ISC_R_FAILURE;
+ ldap_connection_t * conn = NULL;
+ ld_string_t *zone_dn = NULL;
+ ldapdb_rdatalist_t rdatalist;
+ dns_rdatalist_t *rdlist = NULL;
+ dns_rdata_t *soa_rdata = NULL;
+ isc_uint32_t old_serial;
+ isc_uint32_t new_serial;
+ isc_time_t curr_time;
+
+ REQUIRE(inst != NULL);
+ REQUIRE(zone_name != NULL);
+
+ CHECK(str_new(mctx, &zone_dn));
+ CHECK(dnsname_to_dn(inst->zone_register, zone_name, zone_dn));
+ log_debug(5, "incrementing SOA serial number in zone '%s'",
+ str_buf(zone_dn));
+
+ /* get actual SOA serial value */
+ INIT_LIST(rdatalist);
+ CHECK(ldapdb_rdatalist_get(mctx, inst, zone_name, zone_name, &rdatalist));
+ CHECK(ldapdb_rdatalist_findrdatatype(&rdatalist, dns_rdatatype_soa, &rdlist));
+ soa_rdata = ISC_LIST_HEAD(rdlist->rdata);
+ old_serial = dns_soa_getserial(soa_rdata);
+
+ /* Compute the new SOA serial - use actual timestamp.
+ * If timestamp < oldSOAserial then increment old serial by one. */
+ isc_time_now(&curr_time);
+ new_serial = isc_time_seconds(&curr_time);
+ if (new_serial <= old_serial) {
+ /* RFC1982, from bind-9.8.2/bin/named/update.c */
+ new_serial = (old_serial + 1) & 0xFFFFFFFF;
+ if (new_serial == 0)
+ new_serial = 1;
+ }
+ dns_soa_setserial(new_serial, soa_rdata);
+
+ /* write the new serial back to DB */
+ CHECK(ldap_pool_getconnection(inst->pool, &conn));
+ CHECK(modify_soa_record(conn, str_buf(zone_dn), soa_rdata));
+
+cleanup:
+ if (result != ISC_R_SUCCESS)
+ log_error("SOA serial number incrementation failed in zone '%s'",
+ str_buf(zone_dn));
+
+ str_destroy(&zone_dn);
+ ldap_pool_putconnection(inst->pool, &conn);
+ ldapdb_rdatalist_destroy(mctx, &rdatalist);
+ return result;
+}
+
/*
* update_action routine is processed asynchronously so it cannot assume
* anything about state of ldap_inst from where it was sent. The ldap_inst
@@ -2892,7 +2957,7 @@ update_record(isc_task_t *task, isc_event_t *event)
if (PSEARCH_DEL(pevent->chgtype)) {
log_debug(5, "psearch_update: Removing item from cache (%s)",
pevent->dn);
- }
+ }
/* Get cache instance & clean old record */
cache = ldap_instance_getcache(inst);
@@ -2916,6 +2981,11 @@ update_record(isc_task_t *task, isc_event_t *event)
/* Destroy rdatalist, it is now in the cache. */
ldapdb_rdatalist_destroy(mctx, &rdatalist);
}
+
+ // !!!!!!!!!!!!!!! Don't forget to ZONE + RECORD in single object
+ if (inst->soa_autoincrement) {
+ CHECK(increment_soa_serial(mctx, inst, &origin));
+ }
cleanup:
if (result != ISC_R_SUCCESS)
log_error("update_record (psearch) failed for %s. "
--
1.7.7.6
_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel