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