From: Baptiste Assmann Date: Mon, 14 Aug 2017 14:38:29 +0000 (+0200) Subject: MINOR: dns: ability to use a SRV resolution for multiple backends X-Git-Tag: v1.8-dev3~178 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7d2a12662bec18e4a5b2b59c6174da07d2faa29f;p=thirdparty%2Fhaproxy.git MINOR: dns: ability to use a SRV resolution for multiple backends Current code implementation prevents multiple backends from relying on the same SRV resolution. Actually, only the first backend which triggers the resolution gets updated. This patch makes HAProxy to process the whole list of the 'curr' requesters to apply the changes everywhere (hence, the cache also applies to SRV records...) --- diff --git a/src/dns.c b/src/dns.c index b87e1019f9..09ba8f687e 100644 --- a/src/dns.c +++ b/src/dns.c @@ -546,63 +546,91 @@ void dns_resolve_recv(struct dgram_conn *dgram) if (item1->type == DNS_RTYPE_SRV && !LIST_ISEMPTY(&resolution->requester.curr)) { struct dns_srvrq *srvrq; - requester = LIST_NEXT(&resolution->requester.curr, struct dns_requester *, list); - - srvrq = objt_dns_srvrq(requester->requester); - /* We're removing an obsolete entry, remove any associated server */ - if (srvrq) { - struct server *srv; - - for (srv = srvrq->proxy->srv; srv != NULL; srv = srv->next) { - if (srv->srvrq == srvrq && - item1->data_len == - srv->hostname_dn_len && - !memcmp(srv->hostname_dn, item1->target, item1->data_len) && - srv->svc_port == item1->port) { - snr_update_srv_status(srv, 1); - free(srv->hostname); - srv->hostname = NULL; - srv->hostname_dn_len = 0; - free(srv->hostname_dn); - srv->hostname_dn = NULL; - dns_resolution_free(srv->resolvers, srv->resolution); - srv->resolution = dns_resolution_list_get(srv->resolvers, NULL, srv->dns_requester->prefered_query_type); - if (resolution == srv->resolution) - removed_reso = 1; + list_for_each_entry_safe(requester, tmprequester, &resolution->requester.curr, list) { + srvrq = objt_dns_srvrq(requester->requester); + /* We're removing an obsolete entry, remove any associated server */ + if (srvrq) { + struct server *srv; + + for (srv = srvrq->proxy->srv; srv != NULL; srv = srv->next) { + if (srv->srvrq == srvrq && + item1->data_len == + srv->hostname_dn_len && + !memcmp(srv->hostname_dn, item1->target, item1->data_len) && + srv->svc_port == item1->port) { + snr_update_srv_status(srv, 1); + free(srv->hostname); + srv->hostname = NULL; + srv->hostname_dn_len = 0; + free(srv->hostname_dn); + srv->hostname_dn = NULL; + dns_resolution_free(srv->resolvers, srv->resolution); + srv->resolution = dns_resolution_list_get(srv->resolvers, NULL, srv->dns_requester->prefered_query_type); + if (resolution == srv->resolution) + removed_reso = 1; + } } } - } + } /* end of list_for_each(requester) */ } free_dns_answer_item(item1); continue; } if (item1->type == DNS_RTYPE_SRV) { - struct server *srv; - struct dns_srvrq *srvrq; + struct server *srv = NULL; + struct dns_srvrq *srvrq = NULL; if (LIST_ISEMPTY(&resolution->requester.curr)) continue; - requester = LIST_NEXT(&resolution->requester.curr, struct dns_requester *, list); - srvrq = objt_dns_srvrq(requester->requester); - if (!srvrq) - continue; - /* Check if a server already uses that hostname */ - for (srv = srvrq->proxy->srv; srv != NULL; srv = srv->next) { - if (srv->srvrq == srvrq && - item1->data_len == srv->hostname_dn_len && - !memcmp(srv->hostname_dn, item1->target, item1->data_len) && - srv->svc_port == item1->port) { - if (srv->uweight != item1->weight) { + list_for_each_entry_safe(requester, tmprequester, &resolution->requester.curr, list) { + srvrq = objt_dns_srvrq(requester->requester); + if (!srvrq) + continue; + /* Check if a server already uses that hostname */ + for (srv = srvrq->proxy->srv; srv != NULL; srv = srv->next) { + if (srv->srvrq == srvrq && + item1->data_len == srv->hostname_dn_len && + !memcmp(srv->hostname_dn, item1->target, item1->data_len) && + srv->svc_port == item1->port) { + if (srv->uweight != item1->weight) { + char weight[9]; + + snprintf(weight, sizeof(weight), + "%d", item1->weight); + server_parse_weight_change_request(srv, weight); + + } + + break; + } + } + /* If not, try to find a server that is down */ + if (!srv) { + for (srv = srvrq->proxy->srv; srv != NULL; srv = srv->next) { + + if (srv->srvrq == srvrq && + !srv->hostname_dn) + break; + } + if (srv) { char weight[9]; + char hostname[DNS_MAX_NAME_SIZE]; + + if (item1->data_len > DNS_MAX_NAME_SIZE) + continue; + dns_dn_label_to_str(item1->target, hostname, item1->data_len); + update_server_fqdn(srv, hostname, "SRV record"); + srv->svc_port = item1->port; + srv->flags &= ~SRV_F_MAPPORTS; + if ((srv->check.state & CHK_ST_CONFIGURED) && !(srv->flags & SRV_F_CHECKPORT)) + srv->check.port = item1->port; snprintf(weight, sizeof(weight), "%d", item1->weight); server_parse_weight_change_request(srv, weight); - } - break; } } /* If not, try to find a server that is down */