]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
4385. [func] Add support for allow-query and allow-transfer ACLs
authorWitold Krecicki <wpk@isc.org>
Mon, 20 Jun 2016 11:39:44 +0000 (13:39 +0200)
committerWitold Krecicki <wpk@isc.org>
Mon, 20 Jun 2016 11:39:44 +0000 (13:39 +0200)
to catalog zones. [RT #42578]

CHANGES
bin/named/server.c
bin/tests/system/catz/tests.sh
lib/dns/catz.c
lib/dns/include/dns/catz.h
lib/dns/rdata/in_1/apl_42.c
lib/dns/rdata/in_1/apl_42.h
lib/isc/buffer.c
lib/isc/include/isc/buffer.h

diff --git a/CHANGES b/CHANGES
index 8befc560d4ca730d50ab1c95b25bfd49c0ed2eb1..b3a45619e5087d433848e3e51274fbc076d6a838 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+4385.  [func]          Add support for allow-query and allow-transfer ACLs
+                       to catalog zones. [RT #42578]
+
 4384.  [bug]           Change 4256 accidentally disabled logging of the
                        rndc command. [RT #42654]
 
index 64ce1ac48c95b0801cfa3a33d67fd9eabe2da480..830369d63ea2e11979e2fb5c0304a7e4450f2182 100644 (file)
@@ -2041,24 +2041,35 @@ catz_addmodzone_taskaction(isc_task_t *task, isc_event_t *event0) {
        /* Zone shouldn't already exist */
        result = dns_zt_find(ev->view->zonetable,
                             dns_catz_entry_getname(ev->entry), 0, NULL, &zone);
-       if (result == ISC_R_SUCCESS) {
-               isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
-                             NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
-                             "catz: zone \"%s\" already exists", nameb);
-               goto cleanup;
-       } else if (result == DNS_R_PARTIALMATCH) {
-               /* Create our sub-zone anyway */
-               dns_zone_detach(&zone);
-               zone = NULL;
-       } else if (result != ISC_R_NOTFOUND) {
-               isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
-                             NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
-                             "catz: error \"%s\" while trying to "
-                             "add zone \"%s\"",
-                             isc_result_totext(result), nameb);
-               goto cleanup;
-       }
 
+       if (ev->mod == ISC_TRUE) {
+               if (result != ISC_R_SUCCESS) {
+                       isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+                                     NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+                                     "catz: error \"%s\" while trying to"
+                                     "modify zone \"%s\"",
+                                     isc_result_totext(result),
+                                     nameb);
+                       goto cleanup;
+               } else {
+                       dns_zone_detach(&zone);
+               }
+
+       } else {
+               if (result != ISC_R_NOTFOUND && result != DNS_R_PARTIALMATCH) {
+                       isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+                                     NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+                                     "catz: error \"%s\" while trying to"
+                                     "add zone \"%s\"",
+                                     isc_result_totext(result),
+                                     nameb);
+                       goto cleanup;
+               } else { /* this can happen in case of DNS_R_PARTIALMATCH */
+                       if (zone != NULL)
+                               dns_zone_detach(&zone);
+               }
+       }
+       RUNTIME_CHECK(zone == NULL);
        /* Create a config for new zone */
        confbuf = NULL;
        dns_catz_generate_zonecfg(ev->origin, ev->entry, &confbuf);
index 54a86342714e995fc9d40b13eb48038dff21a602..c37b3503974d8e5cc4d475e172bce08ae0533e36 100644 (file)
@@ -372,5 +372,208 @@ grep "'nonexistent' not found; zone files will not be saved" ns2/named.run > /de
 if [ $ret != 0 ]; then echo "I:failed"; fi
 status=`expr $status + $ret`
 
+n=`expr $n + 1`
+echo "I:Adding a domain dom6.example to master via RNDC ($n)"
+ret=0
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns1/dom6.example.db
+echo "@ IN NS invalid." >> ns1/dom6.example.db
+$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953  addzone dom6.example '{type master; file "dom6.example.db";};' || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I:checking that dom6.example is now served by master ($n)"
+ret=0
+$DIG soa dom6.example @10.53.0.1 -p 5300 > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run`
+
+n=`expr $n + 1`
+echo "I:Adding domain dom6.example to catalog1 zone with an allow-query statement ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+    server 10.53.0.1 5300
+    update add 4346f565b4d63ddb99e5d2497ff22d04e878e8f8.zones.catalog1.example 3600 IN PTR dom6.example.
+    update add allow-query.4346f565b4d63ddb99e5d2497ff22d04e878e8f8.zones.catalog1.example 3600 IN APL 1:10.53.0.1/32 !1:10.53.0.0/30 1:0.0.0.0/0
+    send
+END
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I:waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+    sleep 1
+    sed -n "$cur,"'$p' < ns2/named.run | grep "catz: adding zone 'dom6.example' from catalog 'catalog1.example'" > /dev/null && {
+       ret=0
+       break
+    }
+    try=`expr $try + 1`
+done
+try=0
+while test $try -lt 45
+do
+    sleep 1
+    sed -n "$cur,"'$p' < ns2/named.run | grep "transfer of 'dom6.example/IN' from 10.53.0.1#5300: Transfer status: success" > /dev/null && {
+       ret=0
+       break
+    }
+    try=`expr $try + 1`
+done
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I:checking that dom6.example is accessible from 10.53.0.1 ($n)"
+ret=0
+$DIG soa dom6.example -b 10.53.0.1 @10.53.0.2 -p 5300 > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I:checking that dom6.example is not accessible from 10.53.0.2 ($n)"
+ret=0
+$DIG soa dom6.example -b 10.53.0.2 @10.53.0.2 -p 5300 > dig.out.test$n
+grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I:checking that dom6.example is accessible from 10.53.0.5 ($n)"
+ret=0
+$DIG soa dom6.example -b 10.53.0.5 @10.53.0.2 -p 5300 > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run`
+n=`expr $n + 1`
+echo "I:Adding global allow-query and allow-domain ACLs ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+    server 10.53.0.1 5300
+    update add 636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example 3600 IN PTR dom2.example.
+    update add allow-query.catalog1.example 3600 IN APL 1:10.53.0.1/32
+    update add allow-transfer.catalog1.example 3600 IN APL 1:10.53.0.2/32
+    send
+END
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I:waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+    sleep 1
+    sed -n "$cur,"'$p' < ns2/named.run | grep "catz: adding zone 'dom2.example' from catalog 'catalog1.example'" > /dev/null && {
+       ret=0
+       break
+    }
+    try=`expr $try + 1`
+done
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I:checking that dom3.example is accessible from 10.53.0.1 ($n)"
+ret=0
+$DIG soa dom3.example -b 10.53.0.1 @10.53.0.2 -p 5300 > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I:checking that dom3.example is not accessible from 10.53.0.2 ($n)"
+ret=0
+$DIG soa dom3.example -b 10.53.0.2 @10.53.0.2 -p 5300 > dig.out.test$n
+grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I:checking that dom3.example is not AXFR accessible from 10.53.0.1 ($n)"
+ret=0
+$DIG axfr dom3.example -b 10.53.0.1 @10.53.0.2 -p 5300 > dig.out.test$n
+grep "Transfer failed." dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I:checking that dom3.example is AXFR accessible from 10.53.0.2 ($n)"
+ret=0
+$DIG axfr dom3.example -b 10.53.0.2 @10.53.0.2 -p 5300 > dig.out.test$n
+grep -v "Transfer failed." dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run`
+n=`expr $n + 1`
+echo "I:Deleting global allow-query and allow-domain ACLs ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+    server 10.53.0.1 5300
+    update delete allow-query.catalog1.example 3600 IN APL 1:10.53.0.1/32
+    update delete allow-transfer.catalog1.example 3600 IN APL 1:10.53.0.2/32
+    send
+END
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+ret=0
+try=0
+while test $try -lt 45
+do
+    sleep 1
+    sed -n "$cur,"'$p' < ns2/named.run | grep "catz: update_from_db: new zone merged" > /dev/null && {
+       ret=0
+       break
+    }
+    try=`expr $try + 1`
+done
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I:checking that dom3.example is accessible from 10.53.0.1 ($n)"
+ret=0
+$DIG soa dom3.example -b 10.53.0.1 @10.53.0.2 -p 5300 > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I:checking that dom3.example is accessible from 10.53.0.2 ($n)"
+ret=0
+$DIG soa dom3.example -b 10.53.0.2 @10.53.0.2 -p 5300 > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I:checking that dom3.example is AXFR accessible from 10.53.0.1 ($n)"
+ret=0
+$DIG axfr dom3.example -b 10.53.0.1 @10.53.0.2 -p 5300 > dig.out.test$n
+grep -v "Transfer failed." dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I:checking that dom3.example is AXFR accessible from 10.53.0.2 ($n)"
+ret=0
+$DIG axfr dom3.example -b 10.53.0.2 @10.53.0.2 -p 5300 > dig.out.test$n
+grep -v "Transfer failed." dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+
+
 echo "I:exit status: $status"
 [ $status -eq 0 ] || exit 1
index 7032a64e6acde19f9eccfaa00f2a6a3e2c2eb51c..fc97c7fe178f105f846964cecd1027b65e4a1f64 100644 (file)
@@ -94,6 +94,9 @@ dns_catz_options_init(dns_catz_options_t *options) {
        options->masters.keys = NULL;
        options->masters.count = 0;
 
+       options->allow_query = NULL;
+       options->allow_transfer = NULL;
+
        options->in_memory = ISC_FALSE;
        options->min_update_interval = 5;
        options->zonedir = NULL;
@@ -107,6 +110,10 @@ dns_catz_options_free(dns_catz_options_t *options, isc_mem_t *mctx) {
                isc_mem_free(mctx, options->zonedir);
                options->zonedir = NULL;
        }
+       if (options->allow_query != NULL)
+               isc_buffer_free(&options->allow_query);
+       if (options->allow_transfer != NULL)
+               isc_buffer_free(&options->allow_transfer);
 }
 
 isc_result_t
@@ -116,6 +123,8 @@ dns_catz_options_copy(isc_mem_t *mctx, const dns_catz_options_t *src,
        /* TODO error handling */
        REQUIRE(dst != NULL);
        REQUIRE(dst->masters.count == 0);
+       REQUIRE(dst->allow_query == NULL);
+       REQUIRE(dst->allow_transfer == NULL);
 
        if (src->masters.count != 0)
                dns_ipkeylist_copy(mctx, &src->masters, &dst->masters);
@@ -128,6 +137,13 @@ dns_catz_options_copy(isc_mem_t *mctx, const dns_catz_options_t *src,
        if (src->zonedir != NULL)
                dst->zonedir = isc_mem_strdup(mctx, src->zonedir);
 
+       if (src->allow_query != NULL)
+               isc_buffer_dup(mctx, &dst->allow_query, src->allow_query);
+
+       if (src->allow_transfer != NULL)
+               isc_buffer_dup(mctx, &dst->allow_transfer, src->allow_transfer);
+
+
        return (ISC_R_SUCCESS);
 }
 
@@ -135,11 +151,18 @@ isc_result_t
 dns_catz_options_setdefault(isc_mem_t *mctx, const dns_catz_options_t *defaults,
                            dns_catz_options_t *opts)
 {
-       if (opts->masters.count == 0)
-               dns_catz_options_copy(mctx, defaults, opts);
-       else if (defaults->zonedir != NULL)
+       if (opts->masters.count == 0 && defaults->masters.count != 0)
+               dns_ipkeylist_copy(mctx, &defaults->masters, &opts->masters);
+
+       if (defaults->zonedir != NULL)
                opts->zonedir = isc_mem_strdup(mctx, defaults->zonedir);
 
+       if (opts->allow_query == NULL && defaults->allow_query != NULL)
+               isc_buffer_dup(mctx, &opts->allow_query, defaults->allow_query);
+       if (opts->allow_transfer == NULL && defaults->allow_transfer != NULL)
+               isc_buffer_dup(mctx, &opts->allow_transfer,
+                              defaults->allow_transfer);
+
        /* This option is always taken from config, so it's always 'default' */
        opts->in_memory = defaults->in_memory;
        return (ISC_R_SUCCESS);
@@ -237,6 +260,7 @@ dns_catz_entry_validate(const dns_catz_entry_t *entry) {
 
 isc_boolean_t
 dns_catz_entry_cmp(const dns_catz_entry_t *ea, const dns_catz_entry_t *eb) {
+       isc_region_t ra, rb;
        if (ea->opts.masters.count != eb->opts.masters.count)
                return (ISC_FALSE);
 
@@ -244,6 +268,31 @@ dns_catz_entry_cmp(const dns_catz_entry_t *ea, const dns_catz_entry_t *eb) {
                   ea->opts.masters.count * sizeof(isc_sockaddr_t)))
                return (ISC_FALSE);
 
+       /* If one is NULL and the other isn't, the entries don't match */
+       if ((ea->opts.allow_query == NULL) !=
+           (eb->opts.allow_query == NULL))
+               return (ISC_FALSE);
+
+       /* If one is non-NULL, then they both are */
+       if (ea->opts.allow_query != NULL) {
+               isc_buffer_usedregion(ea->opts.allow_query, &ra);
+               isc_buffer_usedregion(eb->opts.allow_query, &rb);
+               if (isc_region_compare(&ra, &rb))
+                       return (ISC_FALSE);
+       }
+
+       /* Repeat the above checks with allow_transfer */
+       if ((ea->opts.allow_transfer == NULL) !=
+           (eb->opts.allow_transfer == NULL))
+               return (ISC_FALSE);
+
+       if (ea->opts.allow_transfer != NULL) {
+               isc_buffer_usedregion(ea->opts.allow_transfer, &ra);
+               isc_buffer_usedregion(eb->opts.allow_transfer, &rb);
+               if (isc_region_compare(&ra, &rb))
+                       return (ISC_FALSE);
+       }
+
        /* xxxwpk TODO compare dscps/keys! */
        return (ISC_TRUE);
 }
@@ -894,6 +943,84 @@ catz_process_ipkl(dns_catz_zone_t *zone, dns_ipkeylist_t *ipkl,
        return (ISC_R_SUCCESS);
 }
 
+static isc_result_t
+catz_process_apl(dns_catz_zone_t *zone, isc_buffer_t **aclbp,
+                dns_rdataset_t *value)
+{
+       isc_result_t result = ISC_R_SUCCESS;
+       dns_rdata_t rdata;
+       dns_rdata_in_apl_t rdata_apl;
+       dns_rdata_apl_ent_t apl_ent;
+       isc_netaddr_t addr;
+       isc_buffer_t *aclb = NULL;
+       unsigned char buf[256]; /* larger than INET6_ADDRSTRLEN */
+
+       REQUIRE(zone != NULL);
+       REQUIRE(aclbp != NULL);
+       REQUIRE(*aclbp == NULL);
+       REQUIRE(DNS_RDATASET_VALID(value));
+       REQUIRE(dns_rdataset_isassociated(value));
+
+       if (value->rdclass != dns_rdataclass_in ||
+           value->type != dns_rdatatype_apl)
+               return (ISC_R_FAILURE);
+
+
+       if (dns_rdataset_count(value) > 1) {
+               isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+                             DNS_LOGMODULE_MASTER, ISC_LOG_WARNING,
+                             "catz: more than one APL entry for member zone, "
+                             "result is undefined");
+       }
+       result = dns_rdataset_first(value);
+       RUNTIME_CHECK(result == ISC_R_SUCCESS);
+       dns_rdata_init(&rdata);
+       dns_rdataset_current(value, &rdata);
+       result = dns_rdata_tostruct(&rdata, &rdata_apl, zone->catzs->mctx);
+       if (result != ISC_R_SUCCESS)
+               return (result);
+       result = isc_buffer_allocate(zone->catzs->mctx, &aclb, 16);
+       isc_buffer_setautorealloc(aclb, ISC_TRUE);
+       if (result != ISC_R_SUCCESS)
+               goto cleanup;
+       for (result = dns_rdata_apl_first(&rdata_apl);
+            result == ISC_R_SUCCESS;
+            result = dns_rdata_apl_next(&rdata_apl)) {
+               result = dns_rdata_apl_current(&rdata_apl, &apl_ent);
+               RUNTIME_CHECK(result == ISC_R_SUCCESS);
+               memset(buf, 0, sizeof(buf));
+               memcpy(buf, apl_ent.data, apl_ent.length);
+               if (apl_ent.family == 1)
+                       isc_netaddr_fromin(&addr, (struct in_addr*) buf);
+               else if (apl_ent.family == 2)
+                       isc_netaddr_fromin6(&addr, (struct in6_addr*) buf);
+               else
+                       continue; /* xxxwpk log it or simply ignore? */
+               if (apl_ent.negative)
+                       isc_buffer_putuint8(aclb, '!');
+               isc_buffer_reserve(&aclb, INET6_ADDRSTRLEN);
+               result = isc_netaddr_totext(&addr, aclb);
+               RUNTIME_CHECK(result == ISC_R_SUCCESS);
+               if ((apl_ent.family == 1 && apl_ent.prefix < 32) ||
+                   (apl_ent.family == 2 && apl_ent.prefix < 128)) {
+                       isc_buffer_putuint8(aclb, '/');
+                       isc_buffer_putdecint(aclb, apl_ent.prefix);
+               }
+               isc_buffer_putstr(aclb, "; ");
+       }
+       if (result == ISC_R_NOMORE)
+               result = ISC_R_SUCCESS;
+       else
+               goto cleanup;
+       *aclbp = aclb;
+       aclb = NULL;
+cleanup:
+       if (aclb != NULL)
+               isc_buffer_free(&aclb);
+       dns_rdata_freestruct(&rdata_apl);
+       return (result);
+}
+
 static isc_result_t
 catz_process_suboption(dns_catz_zone_t *zone, dns_label_t *mhash,
                       catz_opt_t subopt, dns_rdataset_t *value)
@@ -928,10 +1055,11 @@ catz_process_suboption(dns_catz_zone_t *zone, dns_label_t *mhash,
                return (catz_process_ipkl(zone, &entry->opts.masters, value));
                break;
        case CATZ_OPT_ALLOW_QUERY:
-#if 0
-               return (process_apl(zone, &entry->opts))
-#endif
+               return (catz_process_apl(zone, &entry->opts.allow_query,
+                                        value));
        case CATZ_OPT_ALLOW_TRANSFER:
+               return (catz_process_apl(zone, &entry->opts.allow_transfer,
+                                        value));
        default:
                return (ISC_R_FAILURE);
        }
@@ -950,15 +1078,14 @@ catz_process_global_option(dns_catz_zone_t *zone, catz_opt_t option,
        case CATZ_OPT_MASTERS:
                return (catz_process_ipkl(zone, &zone->zoneoptions.masters,
                                          value));
-               break;
        case CATZ_OPT_VERSION:
                return (catz_process_version(zone, value));
-               break;
        case CATZ_OPT_ALLOW_QUERY:
-#if 0
-               return (process_apl(zone, &entry->opts))
-#endif
+               return (catz_process_apl(zone, &zone->zoneoptions.allow_query,
+                                        value));
        case CATZ_OPT_ALLOW_TRANSFER:
+               return (catz_process_apl(zone, &zone->zoneoptions.allow_transfer,
+                                        value));
        default:
                return (ISC_R_FAILURE);
        }
@@ -1128,13 +1255,15 @@ isc_result_t
 dns_catz_generate_zonecfg(dns_catz_zone_t *zone, dns_catz_entry_t *entry,
                          isc_buffer_t **buf)
 {
-       /* We have to generate a text buffer with regular zone config:
+       /*
+        * We have to generate a text buffer with regular zone config:
         * zone foo.bar {
         *      type slave;
         *      masters { ip1 port1; ip2 port2; };
         * }
         */
        isc_buffer_t *buffer = NULL;
+       isc_region_t region;
        isc_result_t result;
        isc_uint32_t i;
        isc_netaddr_t netaddr;
@@ -1183,8 +1312,20 @@ dns_catz_generate_zonecfg(dns_catz_zone_t *zone, dns_catz_entry_t *entry,
                isc_buffer_putstr(buffer, "\";");
 
        }
-       isc_buffer_putstr(buffer, "};");
+       if (entry->opts.allow_query != NULL) {
+               isc_buffer_putstr(buffer, "allow-query { ");
+               isc_buffer_usedregion(entry->opts.allow_query, &region);
+               isc_buffer_copyregion(buffer, &region);
+               isc_buffer_putstr(buffer, "};");
+       }
+       if (entry->opts.allow_transfer != NULL) {
+               isc_buffer_putstr(buffer, "allow-transfer { ");
+               isc_buffer_usedregion(entry->opts.allow_transfer, &region);
+               isc_buffer_copyregion(buffer, &region);
+               isc_buffer_putstr(buffer, "};");
+       }
 
+       isc_buffer_putstr(buffer, "};");
        *buf = buffer;
        return (ISC_R_SUCCESS);
 
@@ -1489,7 +1630,8 @@ dns_catz_postreconfig(dns_catz_zones_t *catzs) {
                isc_ht_iter_current(iter, (void **) &zone);
                if (zone->active == ISC_FALSE) {
                        char cname[DNS_NAME_FORMATSIZE];
-                       dns_name_format(&zone->name, cname, DNS_NAME_FORMATSIZE);
+                       dns_name_format(&zone->name, cname,
+                                       DNS_NAME_FORMATSIZE);
                        isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
                                      DNS_LOGMODULE_MASTER,
                                      ISC_LOG_WARNING,
index f2443d2461ca76b97e60838c6667475ec1b593f8..88cf3fe4f68496f7c72dc22f02d31c24a323eae2 100644 (file)
@@ -54,6 +54,10 @@ struct dns_catz_entry_options {
        /* default-masters definition */
        dns_ipkeylist_t masters;
 
+       /* both as text in config format, NULL if none */
+       isc_buffer_t *allow_query;
+       isc_buffer_t *allow_transfer;
+
        /*
         * Options that are only set in named.conf
         */
index 28eb7f280b3804af4760d980c0122a8995dbe2c3..29866a8b5ac9bcf9c7ffae6a03890079f8289bdd 100644 (file)
@@ -324,7 +324,7 @@ dns_rdata_apl_first(dns_rdata_in_apl_t *apl) {
         */
        INSIST(apl->apl_len > 3U);
        length = apl->apl[apl->offset + 3] & 0x7f;
-       INSIST(length <= apl->apl_len);
+       INSIST(4 + length <= apl->apl_len);
 
        apl->offset = 0;
        return (ISC_R_SUCCESS);
@@ -356,10 +356,10 @@ dns_rdata_apl_next(dns_rdata_in_apl_t *apl) {
         * 16 to 32 bits promotion as 'length' is 32 bits so there is
         * no overflow problems.
         */
-       INSIST(length + apl->offset <= apl->apl_len);
+       INSIST(4 + length + apl->offset <= apl->apl_len);
 
-       apl->offset += apl->apl[apl->offset + 3] & 0x7f;
-       return ((apl->offset >= apl->apl_len) ? ISC_R_SUCCESS : ISC_R_NOMORE);
+       apl->offset += 4 + length;
+       return ((apl->offset < apl->apl_len) ? ISC_R_SUCCESS : ISC_R_NOMORE);
 }
 
 isc_result_t
@@ -381,16 +381,16 @@ dns_rdata_apl_current(dns_rdata_in_apl_t *apl, dns_rdata_apl_ent_t *ent) {
         */
        INSIST(apl->apl_len > 3U);
        INSIST(apl->offset <= apl->apl_len - 4U);
-       length = apl->apl[apl->offset + 3] & 0x7f;
+       length = (apl->apl[apl->offset + 3] & 0x7f);
        /*
         * 16 to 32 bits promotion as 'length' is 32 bits so there is
         * no overflow problems.
         */
-       INSIST(length + apl->offset <= apl->apl_len);
+       INSIST(4 + length + apl->offset <= apl->apl_len);
 
        ent->family = (apl->apl[apl->offset] << 8) + apl->apl[apl->offset + 1];
        ent->prefix = apl->apl[apl->offset + 2];
-       ent->length = apl->apl[apl->offset + 3] & 0x7f;
+       ent->length = length;
        ent->negative = ISC_TF((apl->apl[apl->offset + 3] & 0x80) != 0);
        if (ent->length != 0)
                ent->data = &apl->apl[apl->offset + 4];
@@ -399,6 +399,11 @@ dns_rdata_apl_current(dns_rdata_in_apl_t *apl, dns_rdata_apl_ent_t *ent) {
        return (ISC_R_SUCCESS);
 }
 
+unsigned int
+dns_rdata_apl_count(const dns_rdata_in_apl_t *apl) {
+       return (apl->apl_len);
+}
+
 static inline isc_result_t
 additionaldata_in_apl(ARGS_ADDLDATA) {
        REQUIRE(rdata->type == dns_rdatatype_apl);
index 2d01040ba8998d977b8d3d978cc499188c5ff59e..8d3a1ccb10e4230b92d881fbd2e7fc31f7ab39eb 100644 (file)
@@ -53,4 +53,7 @@ dns_rdata_apl_next(dns_rdata_in_apl_t *);
 isc_result_t
 dns_rdata_apl_current(dns_rdata_in_apl_t *, dns_rdata_apl_ent_t *);
 
+unsigned int
+dns_rdata_apl_count(const dns_rdata_in_apl_t *apl);
+
 #endif /* IN_1_APL_42_H */
index c8cbdd5a5dae0a224c21291d8c5dc3b28eb53713..bcb299992a37c624ee36464d56df4ef88fa59f4c 100644 (file)
@@ -100,7 +100,7 @@ isc__buffer_region(isc_buffer_t *b, isc_region_t *r) {
 }
 
 void
-isc__buffer_usedregion(isc_buffer_t *b, isc_region_t *r) {
+isc__buffer_usedregion(const isc_buffer_t *b, isc_region_t *r) {
        /*
         * Make 'r' refer to the used region of 'b'.
         */
@@ -464,10 +464,55 @@ isc__buffer_putstr(isc_buffer_t *b, const char *source) {
        b->used += l;
 }
 
+void
+isc_buffer_putdecint(isc_buffer_t *b, isc_int64_t v) {
+       unsigned int l=0;
+       unsigned char *cp;
+       char buf[21];
+       isc_result_t result;
+
+       REQUIRE(ISC_BUFFER_VALID(b));
+
+       /* xxxwpk do it more low-level way ? */
+       l = snprintf(buf, 21, "%lld", v);
+       RUNTIME_CHECK(l <= 21);
+       if (b->autore) {
+               result = isc_buffer_reserve(&b, l);
+               REQUIRE(result == ISC_R_SUCCESS);
+       }
+       REQUIRE(isc_buffer_availablelength(b) >= l);
+
+       cp = isc_buffer_used(b);
+       memmove(cp, buf, l);
+       b->used += l;
+}
+
+isc_result_t
+isc_buffer_dup(isc_mem_t *mctx, isc_buffer_t **dstp, const isc_buffer_t *src) {
+       isc_buffer_t *dst = NULL;
+       isc_region_t region;
+       isc_result_t result;
+
+       REQUIRE(dstp != NULL && *dstp == NULL);
+       REQUIRE(ISC_BUFFER_VALID(src));
+
+       isc_buffer_usedregion(src, &region);
+
+       result = isc_buffer_allocate(mctx, &dst, region.length);
+       if (result != ISC_R_SUCCESS)
+               return (result);
+
+       result = isc_buffer_copyregion(dst, &region);
+       RUNTIME_CHECK(result == ISC_R_SUCCESS); /* NOSPACE is impossible */
+       *dstp = dst;
+       return (ISC_R_SUCCESS);
+}
+
 isc_result_t
 isc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r) {
        unsigned char *base;
        unsigned int available;
+       isc_result_t result;
 
        REQUIRE(ISC_BUFFER_VALID(b));
        REQUIRE(r != NULL);
@@ -477,6 +522,11 @@ isc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r) {
         */
        base = isc_buffer_used(b);
        available = isc_buffer_availablelength(b);
+       if (b->autore) {
+               result = isc_buffer_reserve(&b, r->length);
+               if (result != ISC_R_SUCCESS)
+                       return (result);
+       }
        if (r->length > available)
                return (ISC_R_NOSPACE);
        memmove(base, r->base, r->length);
index c71718a24c3dd704c66bff97eae4c12a16ed3056..029c37f6b5b856ab4d060e025984796a156eae19 100644 (file)
@@ -341,7 +341,7 @@ isc__buffer_region(isc_buffer_t *b, isc_region_t *r);
  */
 
 void
-isc__buffer_usedregion(isc_buffer_t *b, isc_region_t *r);
+isc__buffer_usedregion(const isc_buffer_t *b, isc_region_t *r);
 /*!<
  * \brief Make 'r' refer to the used region of 'b'.
  *
@@ -704,6 +704,19 @@ isc__buffer_putstr(isc_buffer_t *b, const char *source);
  *\li  strlen(source) <= isc_buffer_available(b) || b->mctx != NULL
  */
 
+void
+isc_buffer_putdecint(isc_buffer_t *b, isc_int64_t v);
+/*!<
+ * \brief Put decimal representation of 'v' in b
+ *
+ * Requires:
+ *\li  'b' is a valid buffer.
+ *
+ *\li  strlen(dec(v)) <= isc_buffer_available(b) || b->mctx != NULL
+ */
+
+
+
 isc_result_t
 isc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r);
 /*!<
@@ -721,6 +734,22 @@ isc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r);
  *                                     big enough.
  */
 
+isc_result_t
+isc_buffer_dup(isc_mem_t *mctx, isc_buffer_t **dstp, const isc_buffer_t *src);
+/*!<
+ * \brief Allocate 'dst' and copy used contents  of 'src' into it
+ *
+ * Requires:
+ *\li  'dstp' is not NULL and *dst is NULL
+ *\li  'src' is a valid buffer.
+ *
+ * Returns:
+ *
+ *\li  ISC_R_SUCCESS
+ *\li  ISC_R_NOSPACE                   The available region of 'b' is not
+ *                                     big enough.
+ */
+
 ISC_LANG_ENDDECLS
 
 /*