From: Witold Krecicki Date: Mon, 20 Jun 2016 11:39:44 +0000 (+0200) Subject: 4385. [func] Add support for allow-query and allow-transfer ACLs X-Git-Tag: v9.11.0b1~46 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3f06b888ae80a8724b300ab39a4276537b0241cd;p=thirdparty%2Fbind9.git 4385. [func] Add support for allow-query and allow-transfer ACLs to catalog zones. [RT #42578] --- diff --git a/CHANGES b/CHANGES index 8befc560d4c..b3a45619e50 100644 --- 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] diff --git a/bin/named/server.c b/bin/named/server.c index 64ce1ac48c9..830369d63ea 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -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); diff --git a/bin/tests/system/catz/tests.sh b/bin/tests/system/catz/tests.sh index 54a86342714..c37b3503974 100644 --- a/bin/tests/system/catz/tests.sh +++ b/bin/tests/system/catz/tests.sh @@ -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 <> 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 <> 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 <> 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 diff --git a/lib/dns/catz.c b/lib/dns/catz.c index 7032a64e6ac..fc97c7fe178 100644 --- a/lib/dns/catz.c +++ b/lib/dns/catz.c @@ -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, ®ion); + isc_buffer_copyregion(buffer, ®ion); + isc_buffer_putstr(buffer, "};"); + } + if (entry->opts.allow_transfer != NULL) { + isc_buffer_putstr(buffer, "allow-transfer { "); + isc_buffer_usedregion(entry->opts.allow_transfer, ®ion); + isc_buffer_copyregion(buffer, ®ion); + 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, diff --git a/lib/dns/include/dns/catz.h b/lib/dns/include/dns/catz.h index f2443d2461c..88cf3fe4f68 100644 --- a/lib/dns/include/dns/catz.h +++ b/lib/dns/include/dns/catz.h @@ -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 */ diff --git a/lib/dns/rdata/in_1/apl_42.c b/lib/dns/rdata/in_1/apl_42.c index 28eb7f280b3..29866a8b5ac 100644 --- a/lib/dns/rdata/in_1/apl_42.c +++ b/lib/dns/rdata/in_1/apl_42.c @@ -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); diff --git a/lib/dns/rdata/in_1/apl_42.h b/lib/dns/rdata/in_1/apl_42.h index 2d01040ba89..8d3a1ccb10e 100644 --- a/lib/dns/rdata/in_1/apl_42.h +++ b/lib/dns/rdata/in_1/apl_42.h @@ -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 */ diff --git a/lib/isc/buffer.c b/lib/isc/buffer.c index c8cbdd5a5da..bcb299992a3 100644 --- a/lib/isc/buffer.c +++ b/lib/isc/buffer.c @@ -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, ®ion); + + result = isc_buffer_allocate(mctx, &dst, region.length); + if (result != ISC_R_SUCCESS) + return (result); + + result = isc_buffer_copyregion(dst, ®ion); + 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); diff --git a/lib/isc/include/isc/buffer.h b/lib/isc/include/isc/buffer.h index c71718a24c3..029c37f6b5b 100644 --- a/lib/isc/include/isc/buffer.h +++ b/lib/isc/include/isc/buffer.h @@ -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 /*