From f9d18f8633f3bef5f14bc5bc7d86ac886dcfac0e Mon Sep 17 00:00:00 2001 From: Sebastian Reimers Date: Wed, 24 Aug 2022 14:03:49 +0200 Subject: [PATCH] dns/client: fix getaddrinfo duplicates (#486) By default getaddrinfo returns answers for each socktype/protocol. Since we have no knowledge about the used socket type (SOCK_STREAM, SOCK_RAW or SOCK_DGRAM...) we can't filter with hints. So we have to check for duplicates with a list handler. --- src/dns/client.c | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/src/dns/client.c b/src/dns/client.c index a4e2a13b6..2c0045b18 100644 --- a/src/dns/client.c +++ b/src/dns/client.c @@ -778,6 +778,25 @@ static bool query_cache_handler(struct dns_query *q) } +static bool getaddr_dup(struct le *le, void *arg) +{ + struct dnsrr *r1 = list_ledata(le); + struct dnsrr *r2 = arg; + + if (r1->type == DNS_TYPE_A && r2->type == DNS_TYPE_A) { + if (r1->rdata.a.addr == r2->rdata.a.addr) + return true; + } + + if (r1->type == DNS_TYPE_AAAA && r2->type == DNS_TYPE_AAAA) { + if (r1->rdata.aaaa.addr == r2->rdata.aaaa.addr) + return true; + } + + return false; +} + + static int async_getaddrinfo(void *arg) { struct dns_query *q = arg; @@ -801,8 +820,10 @@ static int async_getaddrinfo(void *arg) for (res = res0; res; res = res->ai_next) { struct dnsrr *rr = dns_rr_alloc(); + struct le *le; + if (!rr) { - err = ENOMEM; + err = ENOMEM; goto out; } @@ -829,6 +850,12 @@ static int async_getaddrinfo(void *arg) sa_in6(&sa, rr->rdata.aaaa.addr); } + le = list_apply(&q->rrlv[0], false, getaddr_dup, rr); + if (le) { + mem_deref(rr); + continue; + } + list_append(&q->rrlv[0], &rr->le_priv, rr); } @@ -845,14 +872,17 @@ static int async_getaddrinfo(void *arg) static void getaddrinfo_h(int err, void *arg) { struct dns_query *q = arg; - bool cache = q->dnsc->conf.cache_ttl_max > 0; + const bool cache = q->dnsc->conf.cache_ttl_max > 0; - DEBUG_INFO("--- ANSWER SECTION (getaddrinfo) id: %d ---\n", q->id); + DEBUG_INFO("--- ANSWER SECTION (getaddrinfo) id: %d %s ---\n", q->id, + cache ? "(caching)" : ""); if (!err) { - DEBUG_INFO("%H %s\n", dns_rr_print, - list_ledata(list_head(&q->rrlv[0])), - cache ? "(caching)" : ""); + struct le *le; + LIST_FOREACH(&q->rrlv[0], le) + { + DEBUG_INFO("%H%s\n", dns_rr_print, le->data); + } } query_handler(q, err, &q->rrlv[0], &q->rrlv[1], &q->rrlv[2]);