summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2020-05-17 19:38:29 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2020-05-17 19:38:29 +0000
commit413b26a719d402a30e61c8f93cf7cbf2f19375e3 (patch)
tree663c7611f40817ff1d0eeb031d906ac3f5fb20d6
parent91e808f1db0b76f3625f516ec73a95b4e32decb2 (diff)
downloads6-dns-413b26a719d402a30e61c8f93cf7cbf2f19375e3.tar.xz
Fix resolveq_aaaaa
If s6dns_resolveq_aaaaa gets nodata on the AAAA query for a qualified domain, it will now wait for the answer to the A query on the same qualified domain before returning. Even if it gets nodata, it still means that the domain exists, so it will not wait for results from other qualification attempts.
-rw-r--r--doc/libs6dns/s6dns-message.html3
-rw-r--r--src/libs6dns/s6dns_message_parse.c4
-rw-r--r--src/libs6dns/s6dns_resolveq.c2
-rw-r--r--src/libs6dns/s6dns_resolveq_aaaaa.c50
4 files changed, 37 insertions, 22 deletions
diff --git a/doc/libs6dns/s6dns-message.html b/doc/libs6dns/s6dns-message.html
index 1c5a92d..315b375 100644
--- a/doc/libs6dns/s6dns-message.html
+++ b/doc/libs6dns/s6dns-message.html
@@ -257,7 +257,8 @@ containing <tt>s6dns_message_rr_caa_t</tt> structures.
It stores the packet header into *<em>h</em>. Then, for every RR in the answer,
authority or additional section of the packet, it calls <em>f</em> with the
relevant parameters. <em>data</em> is the extra pointer given to <em>f</em> to
-store information. The function returns 1 if the parsing succeeds. Otherwise it
+store information. If the parsing succeeds, the function returns 2 if the packet
+contains an answer section and 1 if it does not. Otherwise, it
returns -1 if there is a local error unrelated to the packet, or 0 if no
appropriate answer can be decoded from the packet. errno then contains one
of the following values:
diff --git a/src/libs6dns/s6dns_message_parse.c b/src/libs6dns/s6dns_message_parse.c
index 06b7677..4aaee9a 100644
--- a/src/libs6dns/s6dns_message_parse.c
+++ b/src/libs6dns/s6dns_message_parse.c
@@ -10,6 +10,7 @@ int s6dns_message_parse (s6dns_message_header_t *h, char const *packet, unsigned
s6dns_message_counts_t counts ;
unsigned int pos ;
unsigned int section ;
+ int gotans ;
if (!s6dns_message_parse_init(h, &counts, packet, packetlen, &pos)) return 0 ;
switch (h->rcode)
{
@@ -21,6 +22,7 @@ int s6dns_message_parse (s6dns_message_header_t *h, char const *packet, unsigned
case 5 : return (errno = ECONNREFUSED, 0) ;
default: return (errno = EIO, 0) ;
}
+ gotans = !!counts.an ;
section = s6dns_message_parse_skipqd(&counts, packet, packetlen, &pos) ;
while (section)
{
@@ -33,5 +35,5 @@ int s6dns_message_parse (s6dns_message_header_t *h, char const *packet, unsigned
}
section = s6dns_message_parse_next(&counts, &rr, packet, packetlen, &pos) ;
}
- return 1 ;
+ return 1 + gotans ;
}
diff --git a/src/libs6dns/s6dns_resolveq.c b/src/libs6dns/s6dns_resolveq.c
index a2933ee..3c1d22c 100644
--- a/src/libs6dns/s6dns_resolveq.c
+++ b/src/libs6dns/s6dns_resolveq.c
@@ -1,7 +1,9 @@
/* ISC license. */
#include <errno.h>
+
#include <skalibs/error.h>
+
#include <s6-dns/s6dns-domain.h>
#include <s6-dns/s6dns-message.h>
#include <s6-dns/s6dns-engine.h>
diff --git a/src/libs6dns/s6dns_resolveq_aaaaa.c b/src/libs6dns/s6dns_resolveq_aaaaa.c
index f990a7c..460956e 100644
--- a/src/libs6dns/s6dns_resolveq_aaaaa.c
+++ b/src/libs6dns/s6dns_resolveq_aaaaa.c
@@ -13,7 +13,19 @@
#include <s6-dns/s6dns-engine.h>
#include <s6-dns/s6dns-resolve.h>
-#define d_ip46full_from_ip(i, s, h) ((h) ? ip46full_from_ip6(i, s) : ip46full_from_ip4(i, s))
+static int addit (genalloc *ips, char const *s, size_t len, int is6)
+{
+ size_t base = genalloc_len(ip46full_t, ips) ;
+ size_t n = len >> (is6 ? 4 : 2) ;
+ ip46full_t *p ;
+ if (!genalloc_readyplus(ip46full_t, ips, n)) return 0 ;
+ p = genalloc_s(ip46full_t, ips) + base ;
+ for (size_t i = 0 ; i < n ; i++)
+ if (is6) ip46full_from_ip6(p + i, s + (i << 4)) ;
+ else ip46full_from_ip4(p + i, s + (i << 2)) ;
+ genalloc_setlen(ip46full_t, ips, base + n) ;
+ return 1 ;
+}
int s6dns_resolveq_aaaaa_r (genalloc *ips, char const *name, size_t len, s6dns_rci_t const *rci, s6dns_debughook_t const *dbh, tain_t const *deadline, tain_t *stamp)
{
@@ -22,6 +34,8 @@ int s6dns_resolveq_aaaaa_r (genalloc *ips, char const *name, size_t len, s6dns_r
unsigned int best = 0 ;
unsigned int n ;
int e = 0 ;
+ int ans = 0 ;
+ int pinned = 0 ;
unsigned int i = 0 ;
{
s6dns_domain_t domains[rci->rulesnum] ;
@@ -54,12 +68,19 @@ int s6dns_resolveq_aaaaa_r (genalloc *ips, char const *name, size_t len, s6dns_r
{
s6dns_message_header_t h ;
int r ;
+ if (pinned && !(best & 1)) goto end ;
if (best >= n << 1) goto notfound ;
if (error_isagain(dtl[best].status)) break ;
if (dtl[best].status) { errno = dtl[best].status ; goto err ; }
r = s6dns_message_parse(&h, s6dns_engine_packet(dtl + best), s6dns_engine_packetlen(dtl + best), (best & 1) ? &s6dns_message_parse_answer_a : s6dns_message_parse_answer_aaaa, &data) ;
if (r < 0) goto err ;
- else if (r) goto found ;
+ else if (r)
+ {
+ if (!addit(ips, data.s, data.len, !(best & 1))) goto err ;
+ if (r > 1) ans |= 1 + !(best & 1) ;
+ data.len = 0 ;
+ pinned = 1 ;
+ }
else switch (errno)
{
case EBUSY :
@@ -74,25 +95,14 @@ int s6dns_resolveq_aaaaa_r (genalloc *ips, char const *name, size_t len, s6dns_r
}
}
- found:
- s6dns_engine_freen(dtl, n<<1) ;
- {
- size_t len = data.len >> ((best & 1) ? 2 : 4) ;
- size_t i = 0 ;
- size_t base = genalloc_len(ip46full_t, ips) ;
- if (!genalloc_readyplus(ip46full_t, ips, len)) return -1 ;
- for (; i < len ; i++)
- d_ip46full_from_ip(genalloc_s(ip46full_t, ips) + base + i, data.s + (i << ((best & 1) ? 2 : 4)), !(best & 1)) ;
- genalloc_setlen(ip46full_t, ips, base + len) ;
- }
- stralloc_free(&data) ;
- return 1 ;
-
notfound:
- s6dns_engine_freen(dtl, n<<1) ;
- return (errno = e, 0) ;
-
+ errno = e ;
+ ans = 0 ;
+ goto end ;
err:
+ ans = -1 ;
+ end:
+ stralloc_free(&data) ;
s6dns_engine_freen(dtl, n<<1) ;
- return -1 ;
+ return ans ;
}