Jeremie Courreges-Anglas <j...@wxcvbn.org> writes:

> This flag is useful for software that wants to rely on the resolver to
> perform DNSSEC validation.  Among the use cases there are DANE and SSHFP
> records, and the obvious interfaces that I think are useful are
> res_mkquery and getrrsetbyname.  The latter still doesn't support
> DNSSEC, another diff will follow.

Diff on top of the previous one.  I'd like to make getrrsetbyname(3)
"use" RES_USE_DNSSEC again.  This would improve support for ssh -o
VerifyHostKeyDNS (SSHFP records).

The "easy" way would be something like:

Index: getrrsetbyname_async.c
===================================================================
RCS file: /d/cvs/src/lib/libc/asr/getrrsetbyname_async.c,v
retrieving revision 1.11
diff -u -p -p -u -r1.11 getrrsetbyname_async.c
--- getrrsetbyname_async.c      23 Feb 2017 17:04:02 -0000      1.11
+++ getrrsetbyname_async.c      25 Feb 2017 17:25:25 -0000
@@ -42,6 +42,7 @@ getrrsetbyname_async(const char *hostnam
        struct asr_query *as;
 
        ac = _asr_use_resolver(asr);
+       ac->ac_options |= RES_USE_DNSSEC;
        if ((as = _asr_async_new(ac, ASR_GETRRSETBYNAME)) == NULL)
                goto abort; /* errno set */
        as->as_run = getrrsetbyname_async_run;

IIUC this means that we modify the thread-local resolver options used by
subsequent queries.  Cleaning up by resetting the flag before returning
doesn't work in all cases because you could have overlap between two
active getrrsetbyname_async and eg getaddrinfo_async contexts.

The diff below instead adds an as_flags member to struct asr_query, and
merges the flags of the various union members.  struct rrset and struct
ni keep their flags member, as they are a different kind of flags.
A subset of as_flags is passed down to the child ASR_SEND subq, the only
flag that is inherited right now is ASYNC_DNSSEC, which allows
getrrsetbyname_async to communicate its intent.

That's a bit of churn for a small improvement, maybe there is a simpler
diff?

Comments welcome.


diff -pruN asr.1/asr.c asr/asr.c
--- asr.1/asr.c Sat Feb 25 17:57:40 2017
+++ asr/asr.c   Sat Feb 25 17:58:10 2017
@@ -244,7 +244,7 @@ _asr_async_free(struct asr_query *as)
        case ASR_SEND:
                if (as->as_fd != -1)
                        close(as->as_fd);
-               if (as->as.dns.obuf && !(as->as.dns.flags & ASYNC_EXTOBUF))
+               if (as->as.dns.obuf && !(as->as_flags & ASYNC_EXTOBUF))
                        free(as->as.dns.obuf);
                if (as->as.dns.ibuf)
                        free(as->as.dns.ibuf);
diff -pruN asr.1/asr_private.h asr/asr_private.h
--- asr.1/asr_private.h Sat Feb 25 17:57:40 2017
+++ asr/asr_private.h   Sat Feb 25 18:12:23 2017
@@ -156,15 +156,19 @@ struct asr {
 #define        ASYNC_NODATA            0x00000100
 #define        ASYNC_AGAIN             0x00000200
 
+#define        ASYNC_DNSSEC            0x00001000
 #define        ASYNC_EXTOBUF           0x00002000
 
 #define        ASYNC_NO_INET           0x00010000
 #define        ASYNC_NO_INET6          0x00020000
 
+#define        ASYNC_ASR_SEND_MASK     (ASYNC_DNSSEC)
+
 struct asr_query {
        int             (*as_run)(struct asr_query *, struct asr_result *);
        struct asr_ctx  *as_ctx;
        int              as_type;
+       int              as_flags;
        int              as_state;
 
        /* cond */
@@ -183,7 +187,6 @@ struct asr_query {
 
        union {
                struct {
-                       int              flags;
                        uint16_t         reqid;
                        int              class;
                        int              type;
@@ -206,7 +209,6 @@ struct asr_query {
                } dns;
 
                struct {
-                       int              flags;
                        int              class;
                        int              type;
                        char            *name;
@@ -249,7 +251,6 @@ struct asr_query {
                        char            *fqdn;
                        struct addrinfo *aifirst;
                        struct addrinfo *ailast;
-                       int              flags;
                } ai;
 
                struct {
@@ -319,7 +320,8 @@ int _asr_iter_db(struct asr_query *);
 int _asr_parse_namedb_line(FILE *, char **, int, char *, size_t);
 
 /* *_async.c */
-struct asr_query *_res_query_async_ctx(const char *, int, int, struct asr_ctx 
*);
+struct asr_query *_res_query_async_ctx(const char *, int, int,
+    struct asr_ctx *, int);
 struct asr_query *_res_search_async_ctx(const char *, int, int, struct asr_ctx 
*);
 struct asr_query *_gethostbyaddr_async_ctx(const void *, socklen_t, int,
     struct asr_ctx *);
diff -pruN asr.1/getaddrinfo_async.c asr/getaddrinfo_async.c
--- asr.1/getaddrinfo_async.c   Sat Feb 25 17:57:40 2017
+++ asr/getaddrinfo_async.c     Sat Feb 25 18:09:17 2017
@@ -356,18 +356,18 @@ getaddrinfo_async_run(struct asr_query *as, struct asr
                            AS_FAMILY(as) : as->as.ai.hints.ai_family;
 
                        if (family == AF_INET &&
-                           as->as.ai.flags & ASYNC_NO_INET) {
+                           as->as_flags & ASYNC_NO_INET) {
                                async_set_state(as, ASR_STATE_NEXT_FAMILY);
                                break;
                        } else if (family == AF_INET6 &&
-                           as->as.ai.flags & ASYNC_NO_INET6) {
+                           as->as_flags & ASYNC_NO_INET6) {
                                async_set_state(as, ASR_STATE_NEXT_FAMILY);
                                break;
                        }
 
                        as->as_subq = _res_query_async_ctx(as->as.ai.fqdn,
                            C_IN, (family == AF_INET6) ? T_AAAA : T_A,
-                           as->as_ctx);
+                           as->as_ctx, as->as_flags);
 
                        if (as->as_subq == NULL) {
                                if (errno == ENOMEM)
@@ -431,7 +431,7 @@ getaddrinfo_async_run(struct asr_query *as, struct asr
 
        case ASR_STATE_NOT_FOUND:
                /* No result found. Maybe we can try again. */
-               if (as->as.ai.flags & ASYNC_AGAIN)
+               if (as->as_flags & ASYNC_AGAIN)
                        ar->ar_gai_errno = EAI_AGAIN;
                else
                        ar->ar_gai_errno = EAI_NODATA;
@@ -684,7 +684,7 @@ addrconfig_setup(struct asr_query *as)
        if (getifaddrs(&ifa0) == -1)
                return (-1);
 
-       as->as.ai.flags |= ASYNC_NO_INET | ASYNC_NO_INET6;
+       as->as_flags |= ASYNC_NO_INET | ASYNC_NO_INET6;
 
        for (ifa = ifa0; ifa != NULL; ifa = ifa->ifa_next) {
                if (ifa->ifa_addr == NULL)
@@ -697,7 +697,7 @@ addrconfig_setup(struct asr_query *as)
                        if (sinp->sin_addr.s_addr == htonl(INADDR_LOOPBACK))
                                continue;
 
-                       as->as.ai.flags &= ~ASYNC_NO_INET;
+                       as->as_flags &= ~ASYNC_NO_INET;
                        break;
                case PF_INET6:
                        sin6p = (struct sockaddr_in6 *)ifa->ifa_addr;
@@ -708,7 +708,7 @@ addrconfig_setup(struct asr_query *as)
                        if (IN6_IS_ADDR_LINKLOCAL(&sin6p->sin6_addr))
                                continue;
 
-                       as->as.ai.flags &= ~ASYNC_NO_INET6;
+                       as->as_flags &= ~ASYNC_NO_INET6;
                        break;
                }
        }
diff -pruN asr.1/gethostnamadr_async.c asr/gethostnamadr_async.c
--- asr.1/gethostnamadr_async.c Sat Feb 25 17:57:40 2017
+++ asr/gethostnamadr_async.c   Sat Feb 25 18:09:34 2017
@@ -223,7 +223,8 @@ gethostnamadr_async_run(struct asr_query *as, struct a
                                    as->as.hostnamadr.family,
                                    name, sizeof(name));
                                as->as_subq = _res_query_async_ctx(
-                                   name, C_IN, T_PTR, as->as_ctx);
+                                   name, C_IN, T_PTR, as->as_ctx,
+                                   as->as_flags);
                        }
 
                        if (as->as_subq == NULL) {
diff -pruN asr.1/getnetnamadr_async.c asr/getnetnamadr_async.c
--- asr.1/getnetnamadr_async.c  Sat Feb 25 17:57:40 2017
+++ asr/getnetnamadr_async.c    Sat Feb 25 18:09:41 2017
@@ -166,7 +166,7 @@ getnetnamadr_async_run(struct asr_query *as, struct as
                                    as->as.netnamadr.family,
                                    dname, sizeof(dname));
                                as->as_subq = _res_query_async_ctx(
-                                   name, C_IN, type, as->as_ctx);
+                                   name, C_IN, type, as->as_ctx, as->as_flags);
                        }
 
                        if (as->as_subq == NULL) {
diff -pruN asr.1/getrrsetbyname_async.c asr/getrrsetbyname_async.c
--- asr.1/getrrsetbyname_async.c        Sat Feb 25 17:57:40 2017
+++ asr/getrrsetbyname_async.c  Sat Feb 25 18:09:57 2017
@@ -45,6 +45,7 @@ getrrsetbyname_async(const char *hostname, unsigned in
        if ((as = _asr_async_new(ac, ASR_GETRRSETBYNAME)) == NULL)
                goto abort; /* errno set */
        as->as_run = getrrsetbyname_async_run;
+       as->as_flags |= ASYNC_DNSSEC;
 
        as->as.rrset.flags = flags;
        as->as.rrset.class = rdclass;
@@ -98,7 +99,8 @@ getrrsetbyname_async_run(struct asr_query *as, struct 
                    as->as.rrset.name,
                    as->as.rrset.class,
                    as->as.rrset.type,
-                   as->as_ctx);
+                   as->as_ctx,
+                   as->as_flags);
                if (as->as_subq == NULL) {
                        ar->ar_rrset_errno = ERRSET_FAIL;
                        async_set_state(as, ASR_STATE_HALT);
diff -pruN asr.1/res_search_async.c asr/res_search_async.c
--- asr.1/res_search_async.c    Sat Feb 25 17:57:40 2017
+++ asr/res_search_async.c      Sat Feb 25 18:10:11 2017
@@ -121,7 +121,8 @@ res_search_async_run(struct asr_query *as, struct asr_
                        break;
                }
                as->as_subq = _res_query_async_ctx(fqdn,
-                   as->as.search.class, as->as.search.type, as->as_ctx);
+                   as->as.search.class, as->as.search.type, as->as_ctx,
+                   as->as_flags);
                if (as->as_subq == NULL) {
                        ar->ar_errno = errno;
                        if (errno == EINVAL)
@@ -169,9 +170,9 @@ res_search_async_run(struct asr_query *as, struct asr_
 
                if (as->as_dom_flags & ASYNC_DOM_DOMAIN) {
                        if (ar->ar_h_errno == NO_DATA)
-                               as->as.search.flags |= ASYNC_NODATA;
+                               as->as_flags |= ASYNC_NODATA;
                        else if (ar->ar_h_errno == TRY_AGAIN)
-                               as->as.search.flags |= ASYNC_AGAIN;
+                               as->as_flags |= ASYNC_AGAIN;
                }
 
                async_set_state(as, ASR_STATE_NEXT_DOMAIN);
@@ -181,9 +182,9 @@ res_search_async_run(struct asr_query *as, struct asr_
 
                if (as->as.search.saved_h_errno != HERRNO_UNSET)
                        ar->ar_h_errno = as->as.search.saved_h_errno;
-               else if (as->as.search.flags & ASYNC_NODATA)
+               else if (as->as_flags & ASYNC_NODATA)
                        ar->ar_h_errno = NO_DATA;
-               else if (as->as.search.flags & ASYNC_AGAIN)
+               else if (as->as_flags & ASYNC_AGAIN)
                        ar->ar_h_errno = TRY_AGAIN;
                /*
                 * Else, we got the ar_h_errno value set by res_query_async()
diff -pruN asr.1/res_send_async.c asr/res_send_async.c
--- asr.1/res_send_async.c      Sat Feb 25 17:57:40 2017
+++ asr/res_send_async.c        Sat Feb 25 19:13:13 2017
@@ -67,7 +67,7 @@ res_send_async(const unsigned char *buf, int buflen, v
        }
        as->as_run = res_send_async_run;
 
-       as->as.dns.flags |= ASYNC_EXTOBUF;
+       as->as_flags |= ASYNC_EXTOBUF;
        as->as.dns.obuf = (unsigned char *)buf;
        as->as.dns.obuflen = buflen;
        as->as.dns.obufsize = buflen;
@@ -110,7 +110,7 @@ res_query_async(const char *name, int class, int type,
        DPRINT("asr: res_query_async(\"%s\", %i, %i)\n", name, class, type);
 
        ac = _asr_use_resolver(asr);
-       as = _res_query_async_ctx(name, class, type, ac);
+       as = _res_query_async_ctx(name, class, type, ac, 0);
        _asr_ctx_unref(ac);
 
        return (as);
@@ -118,7 +118,8 @@ res_query_async(const char *name, int class, int type,
 DEF_WEAK(res_query_async);
 
 struct asr_query *
-_res_query_async_ctx(const char *name, int class, int type, struct asr_ctx 
*a_ctx)
+_res_query_async_ctx(const char *name, int class, int type,
+    struct asr_ctx *a_ctx, int a_flags)
 {
        struct asr_query        *as;
 
@@ -127,6 +128,7 @@ _res_query_async_ctx(const char *name, int class, int 
        if ((as = _asr_async_new(a_ctx, ASR_SEND)) == NULL)
                return (NULL); /* errno set */
        as->as_run = res_send_async_run;
+       as->as_flags = a_flags & ASYNC_ASR_SEND_MASK;
 
        /* This adds a "." to name if it doesn't already has one.
         * That's how res_query() behaves (through res_mkquery").
@@ -345,8 +347,9 @@ setup_query(struct asr_query *as, const char *name, co
        struct asr_dns_header   h;
        char                    fqdn[MAXDNAME];
        char                    dname[MAXDNAME];
+       int                     dnssec_do;
 
-       if (as->as.dns.flags & ASYNC_EXTOBUF) {
+       if (as->as_flags & ASYNC_EXTOBUF) {
                errno = EINVAL;
                DPRINT("attempting to write in user packet");
                return (-1);
@@ -372,20 +375,22 @@ setup_query(struct asr_query *as, const char *name, co
        }
        as->as.dns.obuflen = 0;
 
+       dnssec_do = (as->as_ctx->ac_options & RES_USE_DNSSEC) ||
+               (as->as_flags & ASYNC_DNSSEC);
+
        memset(&h, 0, sizeof h);
        h.id = res_randomid();
        if (as->as_ctx->ac_options & RES_RECURSE)
                h.flags |= RD_MASK;
        h.qdcount = 1;
-       if (as->as_ctx->ac_options & (RES_USE_EDNS0 | RES_USE_DNSSEC))
+       if (as->as_ctx->ac_options & RES_USE_EDNS0 || dnssec_do)
                h.arcount = 1;
 
        _asr_pack_init(&p, as->as.dns.obuf, as->as.dns.obufsize);
        _asr_pack_header(&p, &h);
        _asr_pack_query(&p, type, class, dname);
-       if (as->as_ctx->ac_options & (RES_USE_EDNS0 | RES_USE_DNSSEC))
-               _asr_pack_edns0(&p, MAXPACKETSZ,
-                   as->as_ctx->ac_options & RES_USE_DNSSEC);
+       if (as->as_ctx->ac_options & RES_USE_EDNS0 || dnssec_do)
+               _asr_pack_edns0(&p, MAXPACKETSZ, dnssec_do);
        if (p.err) {
                DPRINT("error packing query");
                errno = EINVAL;


-- 
jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF  DDCC 0DFA 74AE 1524 E7EE

Reply via email to