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.
The first hunk is not supposed to be committed, it is only here for basic testing (add "options dnssec" to resolv.conf). Other testing could involve postfix or exim. Since RES_USE_DNSSEC now actually adds an EDNS0 OPT record to the outgoing packet, one can be concerned with problems with resolvers out there. Windows seems to have a way to disable EDNS0, I am not aware of existing mechanisms elsewhere. Thoughts? ok? Index: asr/asr.c =================================================================== RCS file: /d/cvs/src/lib/libc/asr/asr.c,v retrieving revision 1.56 diff -u -p -r1.56 asr.c --- asr/asr.c 23 Feb 2017 17:04:02 -0000 1.56 +++ asr/asr.c 25 Feb 2017 16:04:30 -0000 @@ -597,6 +597,8 @@ pass0(char **tok, int n, struct asr_ctx ac->ac_options |= RES_USEVC; else if (!strcmp(tok[i], "edns0")) ac->ac_options |= RES_USE_EDNS0; + else if (!strcmp(tok[i], "dnssec")) + ac->ac_options |= RES_USE_DNSSEC; else if ((!strncmp(tok[i], "ndots:", 6))) { e = NULL; d = strtonum(tok[i] + 6, 1, 16, &e); Index: asr/asr_private.h =================================================================== RCS file: /d/cvs/src/lib/libc/asr/asr_private.h,v retrieving revision 1.43 diff -u -p -r1.43 asr_private.h --- asr/asr_private.h 23 Feb 2017 17:04:02 -0000 1.43 +++ asr/asr_private.h 25 Feb 2017 14:45:16 -0000 @@ -297,7 +297,7 @@ __BEGIN_HIDDEN_DECLS void _asr_pack_init(struct asr_pack *, char *, size_t); int _asr_pack_header(struct asr_pack *, const struct asr_dns_header *); int _asr_pack_query(struct asr_pack *, uint16_t, uint16_t, const char *); -int _asr_pack_edns0(struct asr_pack *, uint16_t); +int _asr_pack_edns0(struct asr_pack *, uint16_t, int); void _asr_unpack_init(struct asr_unpack *, const char *, size_t); int _asr_unpack_header(struct asr_unpack *, struct asr_dns_header *); int _asr_unpack_query(struct asr_unpack *, struct asr_dns_query *); Index: asr/asr_utils.c =================================================================== RCS file: /d/cvs/src/lib/libc/asr/asr_utils.c,v retrieving revision 1.16 diff -u -p -r1.16 asr_utils.c --- asr/asr_utils.c 19 Feb 2017 12:02:30 -0000 1.16 +++ asr/asr_utils.c 25 Feb 2017 16:06:01 -0000 @@ -423,12 +423,19 @@ _asr_pack_query(struct asr_pack *p, uint } int -_asr_pack_edns0(struct asr_pack *p, uint16_t pktsz) +_asr_pack_edns0(struct asr_pack *p, uint16_t pktsz, int dnssec_do) { + DPRINT("asr EDNS0 pktsz:%hu dnssec:%s\n", pktsz, + dnssec_do ? "yes" : "no"); + pack_dname(p, ""); /* root */ pack_u16(p, T_OPT); /* OPT */ pack_u16(p, pktsz); /* UDP payload size */ - pack_u32(p, 0); /* extended RCODE and flags */ + + /* extended RCODE and flags */ + pack_u16(p, 0); + pack_u16(p, dnssec_do ? DNS_MESSAGEEXTFLAG_DO : 0); + pack_u16(p, 0); /* RDATA len */ return (p->err) ? (-1) : (0); Index: asr/res_mkquery.c =================================================================== RCS file: /d/cvs/src/lib/libc/asr/res_mkquery.c,v retrieving revision 1.10 diff -u -p -r1.10 res_mkquery.c --- asr/res_mkquery.c 18 Feb 2017 19:23:05 -0000 1.10 +++ asr/res_mkquery.c 25 Feb 2017 14:45:16 -0000 @@ -61,14 +61,15 @@ res_mkquery(int op, const char *dname, i if (ac->ac_options & RES_RECURSE) h.flags |= RD_MASK; h.qdcount = 1; - if (ac->ac_options & RES_USE_EDNS0) + if (ac->ac_options & (RES_USE_EDNS0 | RES_USE_DNSSEC)) h.arcount = 1; _asr_pack_init(&p, buf, buflen); _asr_pack_header(&p, &h); _asr_pack_query(&p, type, class, dn); - if (ac->ac_options & RES_USE_EDNS0) - _asr_pack_edns0(&p, MAXPACKETSZ); + if (ac->ac_options & (RES_USE_EDNS0 | RES_USE_DNSSEC)) + _asr_pack_edns0(&p, MAXPACKETSZ, + ac->ac_options & RES_USE_DNSSEC); _asr_ctx_unref(ac); Index: asr/res_send_async.c =================================================================== RCS file: /d/cvs/src/lib/libc/asr/res_send_async.c,v retrieving revision 1.32 diff -u -p -r1.32 res_send_async.c --- asr/res_send_async.c 18 Feb 2017 22:25:13 -0000 1.32 +++ asr/res_send_async.c 25 Feb 2017 14:45:16 -0000 @@ -377,14 +377,15 @@ setup_query(struct asr_query *as, const if (as->as_ctx->ac_options & RES_RECURSE) h.flags |= RD_MASK; h.qdcount = 1; - if (as->as_ctx->ac_options & RES_USE_EDNS0) + if (as->as_ctx->ac_options & (RES_USE_EDNS0 | RES_USE_DNSSEC)) 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) - _asr_pack_edns0(&p, MAXPACKETSZ); + 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 (p.err) { DPRINT("error packing query"); errno = EINVAL; Index: net/resolver.3 =================================================================== RCS file: /d/cvs/src/lib/libc/net/resolver.3,v retrieving revision 1.36 diff -u -p -r1.36 resolver.3 --- net/resolver.3 18 Feb 2017 19:23:05 -0000 1.36 +++ net/resolver.3 20 Feb 2017 06:27:31 -0000 @@ -199,9 +199,6 @@ uses 4096 bytes as input buffer size. Request that the resolver uses Domain Name System Security Extensions (DNSSEC), as defined in RFCs 4033, 4034, and 4035. -On -.Ox -this option does nothing. .El .Pp The -- jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF DDCC 0DFA 74AE 1524 E7EE