From 8c2ede6edcc917496eb7d6603c05427cbb9793cc Mon Sep 17 00:00:00 2001
From: Mark Andrews <marka@isc.org>
Date: Wed, 4 May 2022 15:40:53 +1000
Subject: [PATCH] Process learned records as well as glue

(cherry picked from commit 07c828531cb49deeba3e14d7a5ffef7934973562)
Conflict: adapt seg2 and delete rpz_rewrite modify
Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/8c2ede6edcc917496eb7d6603c05427cbb9793cc
---
 lib/ns/query.c | 167 ++++++++++++++++++++++++++++---------------------
 1 file changed, 94 insertions(+), 73 deletions(-)

diff --git a/lib/ns/query.c b/lib/ns/query.c
index 5ba732f..e6b25bc 100644
--- a/lib/ns/query.c
+++ b/lib/ns/query.c
@@ -2774,7 +2774,7 @@ query_rpzfetch(ns_client_t *client, dns_name_t *qname, dns_rdatatype_t type) {
  */
 static isc_result_t
 rpz_rrset_find(ns_client_t *client, dns_name_t *name, dns_rdatatype_t type,
-	       dns_rpz_type_t rpz_type, dns_db_t **dbp,
+	       unsigned int options, dns_rpz_type_t rpz_type, dns_db_t **dbp,
 	       dns_dbversion_t *version, dns_rdataset_t **rdatasetp,
 	       bool resuming) {
 	dns_rpz_st_t *st;
@@ -2843,7 +2843,7 @@ rpz_rrset_find(ns_client_t *client, dns_name_t *name, dns_rdatatype_t type,
 	found = dns_fixedname_initname(&fixed);
 	dns_clientinfomethods_init(&cm, ns_client_sourceip);
 	dns_clientinfo_init(&ci, client, NULL);
-	result = dns_db_findext(*dbp, name, version, type, DNS_DBFIND_GLUEOK,
+	result = dns_db_findext(*dbp, name, version, type, options,
 				client->now, &node, found, &cm, &ci, *rdatasetp,
 				NULL);
 	if (result == DNS_R_DELEGATION && is_zone && USECACHE(client)) {
@@ -3588,82 +3588,104 @@ rpz_rewrite_ip_rrset(ns_client_t *client, dns_name_t *name,
 	struct in_addr ina;
 	struct in6_addr in6a;
 	isc_result_t result;
+	unsigned int options = DNS_DBFIND_GLUEOK;
+	bool done = false;
 
 	CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ip_rrset");
 
-	zbits = rpz_get_zbits(client, ip_type, rpz_type);
-	if (zbits == 0) {
-		return (ISC_R_SUCCESS);
-	}
+	do {
+		zbits = rpz_get_zbits(client, ip_type, rpz_type);
+		if (zbits == 0) {
+			return (ISC_R_SUCCESS);
+		}
 
-	/*
-	 * Get the A or AAAA rdataset.
-	 */
-	result = rpz_rrset_find(client, name, ip_type, rpz_type, ip_dbp,
-				ip_version, ip_rdatasetp, resuming);
-	switch (result) {
-	case ISC_R_SUCCESS:
-	case DNS_R_GLUE:
-	case DNS_R_ZONECUT:
-		break;
-	case DNS_R_EMPTYNAME:
-	case DNS_R_EMPTYWILD:
-	case DNS_R_NXDOMAIN:
-	case DNS_R_NCACHENXDOMAIN:
-	case DNS_R_NXRRSET:
-	case DNS_R_NCACHENXRRSET:
-	case ISC_R_NOTFOUND:
-		return (ISC_R_SUCCESS);
-	case DNS_R_DELEGATION:
-	case DNS_R_DUPLICATE:
-	case DNS_R_DROP:
-		return (result);
-	case DNS_R_CNAME:
-	case DNS_R_DNAME:
-		rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, name, rpz_type,
-			     "NS address rewrite rrset", result);
-		return (ISC_R_SUCCESS);
-	default:
-		if (client->query.rpz_st->m.policy != DNS_RPZ_POLICY_ERROR) {
-			client->query.rpz_st->m.policy = DNS_RPZ_POLICY_ERROR;
-			rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, name,
+		/*
+		 * Get the A or AAAA rdataset.
+		 */
+		result = rpz_rrset_find(client, name, ip_type, options,
+					rpz_type, ip_dbp, ip_version,
+					ip_rdatasetp, resuming);
+		switch (result) {
+		case ISC_R_SUCCESS:
+		case DNS_R_GLUE:
+		case DNS_R_ZONECUT:
+			break;
+		case DNS_R_EMPTYNAME:
+		case DNS_R_EMPTYWILD:
+		case DNS_R_NXDOMAIN:
+		case DNS_R_NCACHENXDOMAIN:
+		case DNS_R_NXRRSET:
+		case DNS_R_NCACHENXRRSET:
+		case ISC_R_NOTFOUND:
+			return (ISC_R_SUCCESS);
+		case DNS_R_DELEGATION:
+		case DNS_R_DUPLICATE:
+		case DNS_R_DROP:
+			return (result);
+		case DNS_R_CNAME:
+		case DNS_R_DNAME:
+			rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, name,
 				     rpz_type, "NS address rewrite rrset",
 				     result);
+			return (ISC_R_SUCCESS);
+		default:
+			if (client->query.rpz_st->m.policy !=
+			    DNS_RPZ_POLICY_ERROR) {
+				client->query.rpz_st->m.policy =
+					DNS_RPZ_POLICY_ERROR;
+				rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, name,
+					     rpz_type,
+					     "NS address rewrite rrset",
+					     result);
+			}
+			CTRACE(ISC_LOG_ERROR,
+			       "rpz_rewrite_ip_rrset: unexpected "
+			       "result");
+			return (DNS_R_SERVFAIL);
 		}
-		CTRACE(ISC_LOG_ERROR, "rpz_rewrite_ip_rrset: unexpected "
-				      "result");
-		return (DNS_R_SERVFAIL);
-	}
 
-	/*
-	 * Check all of the IP addresses in the rdataset.
-	 */
-	for (result = dns_rdataset_first(*ip_rdatasetp);
-	     result == ISC_R_SUCCESS; result = dns_rdataset_next(*ip_rdatasetp))
-	{
-		dns_rdata_t rdata = DNS_RDATA_INIT;
-		dns_rdataset_current(*ip_rdatasetp, &rdata);
-		switch (rdata.type) {
-		case dns_rdatatype_a:
-			INSIST(rdata.length == 4);
-			memmove(&ina.s_addr, rdata.data, 4);
-			isc_netaddr_fromin(&netaddr, &ina);
-			break;
-		case dns_rdatatype_aaaa:
-			INSIST(rdata.length == 16);
-			memmove(in6a.s6_addr, rdata.data, 16);
-			isc_netaddr_fromin6(&netaddr, &in6a);
-			break;
-		default:
-			continue;
+		/*
+		 * If we are processing glue setup for the next loop
+		 * otherwise we are done.
+		 */
+		if (result == DNS_R_GLUE) {
+			options = 0;
+		} else {
+			done = true;
 		}
 
-		result = rpz_rewrite_ip(client, &netaddr, qtype, rpz_type,
-					zbits, p_rdatasetp);
-		if (result != ISC_R_SUCCESS) {
-			return (result);
+		/*
+		 * Check all of the IP addresses in the rdataset.
+		 */
+		for (result = dns_rdataset_first(*ip_rdatasetp);
+		     result == ISC_R_SUCCESS;
+		     result = dns_rdataset_next(*ip_rdatasetp))
+		{
+			dns_rdata_t rdata = DNS_RDATA_INIT;
+			dns_rdataset_current(*ip_rdatasetp, &rdata);
+			switch (rdata.type) {
+			case dns_rdatatype_a:
+				INSIST(rdata.length == 4);
+				memmove(&ina.s_addr, rdata.data, 4);
+				isc_netaddr_fromin(&netaddr, &ina);
+				break;
+			case dns_rdatatype_aaaa:
+				INSIST(rdata.length == 16);
+				memmove(in6a.s6_addr, rdata.data, 16);
+				isc_netaddr_fromin6(&netaddr, &in6a);
+				break;
+			default:
+				continue;
+			}
+
+			result = rpz_rewrite_ip(client, &netaddr, qtype,
+						rpz_type, zbits, p_rdatasetp);
+			if (result != ISC_R_SUCCESS) {
+				return (result);
+			}
 		}
-	}
+	} while (!done &&
+		 client->query.rpz_st->m.policy == DNS_RPZ_POLICY_MISS);
 
 	return (ISC_R_SUCCESS);
 }
-- 
2.27.0

