BUG/MEDIUM: resolvers: Trigger a DNS resolution if an ADD item is obsolete

When a ADD item attached to a SRV item is removed because it is obsolete, we
must trigger a DNS resolution to be sure the hostname still resolves or
not. There is no other way to be the entry is still valid. And we cannot set
the server in RMAINT immediatly, because a DNS server may be inconsitent and
may stop to add some additionnal records.

The opposite is also true. If a valid ADD item is still attached to a SRV
item, any DNS resolution must be stopped. There is no reason to perform
extra resolution in this case.

This patch must be backported as far as 2.2.

(cherry picked from commit 3e0600fbbfee7daf957033505d56bc8dcc874185)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
diff --git a/src/dns.c b/src/dns.c
index b7f9519..9285a9b 100644
--- a/src/dns.c
+++ b/src/dns.c
@@ -630,6 +630,9 @@
 
 		/* clean up obsolete Additional record */
 		if (ar_item && (ar_item->last_seen + resolvers->hold.obsolete / 1000) < now.tv_sec) {
+			/* Cleaning up the AR item will trigger an extra DNS  resolution, except if the SRV
+			 * item is also obsolete.
+			 */
 			pool_free(dns_answer_item_pool, ar_item);
 			item->ar_item = NULL;
 		}
@@ -704,14 +707,17 @@
 
 			/* And update this server, if found (srv is locked here) */
 			if (srv) {
+				/* re-enable DNS resolution for this server by default */
+				srv->flags &= ~SRV_F_NO_RESOLUTION;
+
 				/* Check if an Additional Record is associated to this SRV record.
 				 * Perform some sanity checks too to ensure the record can be used.
 				 * If all fine, we simply pick up the IP address found and associate
-				 * it to the server.
+				 * it to the server. And DNS resolution is disabled for this server.
 				 */
 				if ((item->ar_item != NULL) &&
 				    (item->ar_item->type == DNS_RTYPE_A || item->ar_item->type == DNS_RTYPE_AAAA))
-				    {
+				{
 
 					switch (item->ar_item->type) {
 						case DNS_RTYPE_A:
@@ -723,6 +729,11 @@
 					}
 
 					srv->flags |= SRV_F_NO_RESOLUTION;
+
+					/* Unlink A/AAAA resolution for this server if there is an AR item.
+					 * It is usless to perform an extra resolution
+					 */
+					dns_unlink_resolution(srv->dns_requester);
 				}
 
 				if (!srv->hostname_dn) {
@@ -739,6 +750,14 @@
 						send_log(srv->proxy, LOG_NOTICE, "%s", msg);
 				}
 
+				if (!(srv->flags & SRV_F_NO_RESOLUTION)) {
+					/* If there is no AR item responsible of the FQDN resolution,
+					 * trigger a dedicated DNS resolution
+					 */
+					if (!srv->dns_requester || !srv->dns_requester->resolution)
+						dns_link_resolution(srv, OBJ_TYPE_SERVER, 1);
+				}
+
 				/* Update the server status */
 				snr_update_srv_status(srv, (srv->addr.ss_family != AF_INET && srv->addr.ss_family != AF_INET6));