Commit 3f06b888 authored by Witold Krecicki's avatar Witold Krecicki
Browse files

4385. [func] Add support for allow-query and allow-transfer ACLs

			to catalog zones. [RT #42578]
parent c1bf332c
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]
......
......@@ -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);
......
......@@ -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
......@@ -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,
......
......@@ -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
*/
......
......@@ -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);
......
......@@ -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 */
......@@ -100,7 +100,7 @@ isc__buffer_region(isc_buffer_t *b, isc_region_t *r) {