From 01827e38817bb7bf1e848a6c627406209c2fe551 Mon Sep 17 00:00:00 2001 From: Martin Nagy Date: Tue, 28 Jul 2009 16:04:28 +0200 Subject: Allow updating of the SOA record Since the SOA record is special for us, as we store it in multiple LDAP attributes, it was ignored until now. This is now fixed, but we only allow changes to the numeric attributes: serial, refresh, retry, expire and minimum. Resolves ticket #5 --- src/ldap_helper.c | 60 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 11 deletions(-) diff --git a/src/ldap_helper.c b/src/ldap_helper.c index a85c568..ba774ff 100644 --- a/src/ldap_helper.c +++ b/src/ldap_helper.c @@ -1928,32 +1928,70 @@ cleanup: } /* - * TODO: Handle updating of the SOA record, use the settings to determine if - * this is allowed. + * Modify the SOA record of a zone, where DN of the zone is 'zone_dn'. + * The SOA record is a special case because we need to update serial, + * refresh, retry, expire and minimum attributes for each SOA record. */ +static isc_result_t +modify_soa_record(ldap_connection_t *ldap_conn, const char *zone_dn, + dns_rdata_t *rdata) +{ + isc_mem_t *mctx = ldap_conn->database->mctx; + dns_rdata_soa_t soa; + LDAPMod change[5]; + LDAPMod *changep[6] = { + &change[0], &change[1], &change[2], &change[3], &change[4], + NULL + }; + +#define SET_LDAP_MOD(index, name) \ + change[index].mod_op = LDAP_MOD_REPLACE; \ + change[index].mod_type = "idnsSOA" #name; \ + change[index].mod_values = alloca(2 * sizeof(char *)); \ + change[index].mod_values[0] = alloca(sizeof(soa.name) + 1); \ + change[index].mod_values[1] = NULL; \ + snprintf(change[index].mod_values[0], sizeof(soa.name) + 1, "%d", soa.name) + + dns_rdata_tostruct(rdata, (void *)&soa, mctx); + + SET_LDAP_MOD(0, serial); + SET_LDAP_MOD(1, refresh); + SET_LDAP_MOD(2, retry); + SET_LDAP_MOD(3, expire); + SET_LDAP_MOD(4, minimum); + + dns_rdata_freestruct((void *)&soa); + + return ldap_modify_do(ldap_conn, zone_dn, changep); + +#undef SET_LDAP_MOD +} + static isc_result_t modify_ldap_common(dns_name_t *owner, ldap_instance_t *ldap_inst, dns_rdatalist_t *rdlist, int mod_op) { isc_result_t result; - isc_mem_t *mctx; + isc_mem_t *mctx = ldap_inst->mctx; ldap_connection_t *ldap_conn = NULL; ld_string_t *owner_dn = NULL; - LDAPMod *change[3] = { NULL, NULL, NULL }; - - mctx = ldap_inst->mctx; + LDAPMod *change[3] = { NULL }; - if (rdlist->type == dns_rdatatype_soa) { - result = ISC_R_SUCCESS; - goto cleanup; - } + if (rdlist->type == dns_rdatatype_soa && mod_op == LDAP_MOD_DELETE) + return ISC_R_SUCCESS; ldap_conn = get_connection(ldap_inst); CHECK(str_new(mctx, &owner_dn)); CHECK(dnsname_to_dn(ldap_inst, owner, owner_dn)); - CHECK(ldap_rdatalist_to_ldapmod(mctx, rdlist, &change[0], mod_op)); + if (rdlist->type == dns_rdatatype_soa) { + result = modify_soa_record(ldap_conn, str_buf(owner_dn), + HEAD(rdlist->rdata)); + goto cleanup; + } + + CHECK(ldap_rdatalist_to_ldapmod(mctx, rdlist, &change[0], mod_op)); if (mod_op == LDAP_MOD_ADD) { /* for now always replace the ttl on add */ CHECK(ldap_rdttl_to_ldapmod(mctx, rdlist, &change[1])); -- cgit