Seems to work fine here. We already use a 4096 bytes input buffer, the edns0 option makes libc advertize this to the DNS resolver. nsd, unbound, dig(1) and ports/net/isc-bind support this feature. I'm not suggesting that we use it by default right now, but this could be a desirable change.
ok? Index: share/man/man5/resolv.conf.5 =================================================================== RCS file: /d/cvs/src/share/man/man5/resolv.conf.5,v retrieving revision 1.51 diff -u -p -r1.51 resolv.conf.5 --- share/man/man5/resolv.conf.5 24 Jan 2017 12:43:00 -0000 1.51 +++ share/man/man5/resolv.conf.5 18 Feb 2017 14:33:37 -0000 @@ -258,21 +258,21 @@ lines are able to handle the extension. On .Ox this option does nothing. -.\" .Pp -.\" To verify whether a server supports EDNS, -.\" query it using the -.\" .Xr dig 1 -.\" query option -.\" .Li +edns=0 : -.\" the reply indicates compliance (EDNS version 0) -.\" and whether a UDP packet larger than 512 bytes can be used. -.\" Note that EDNS0 can cause the server to send packets -.\" large enough to require fragmentation. -.\" Other factors such as packet filters may impede these, -.\" particularly if there is a reduced MTU, -.\" as is often the case with -.\" .Xr pppoe 4 -.\" or with tunnels. +.Pp +To verify whether a server supports EDNS, +query it using the +.Xr dig 1 +query option +.Li +edns=0 : +the reply indicates compliance (EDNS version 0) +and whether a UDP packet larger than 512 bytes can be used. +Note that EDNS0 can cause the server to send packets +large enough to require fragmentation. +Other factors such as packet filters may impede these, +particularly if there is a reduced MTU, +as is often the case with +.Xr pppoe 4 +or with tunnels. .It Cm inet6 Enables support for IPv6-only applications, by setting RES_USE_INET6 in _res.options (see Index: lib/libc/asr/asr.c =================================================================== RCS file: /d/cvs/src/lib/libc/asr/asr.c,v retrieving revision 1.54 diff -u -p -r1.54 asr.c --- lib/libc/asr/asr.c 18 Jun 2016 15:25:28 -0000 1.54 +++ lib/libc/asr/asr.c 16 Feb 2017 15:36:30 -0000 @@ -603,6 +603,8 @@ pass0(char **tok, int n, struct asr_ctx for (i = 1; i < n; i++) { if (!strcmp(tok[i], "tcp")) ac->ac_options |= RES_USEVC; + else if (!strcmp(tok[i], "edns0")) + ac->ac_options |= RES_USE_EDNS0; else if ((!strncmp(tok[i], "ndots:", 6))) { e = NULL; d = strtonum(tok[i] + 6, 1, 16, &e); Index: lib/libc/asr/asr_private.h =================================================================== RCS file: /d/cvs/src/lib/libc/asr/asr_private.h,v retrieving revision 1.41 diff -u -p -r1.41 asr_private.h --- lib/libc/asr/asr_private.h 17 Feb 2017 22:24:45 -0000 1.41 +++ lib/libc/asr/asr_private.h 18 Feb 2017 10:44:56 -0000 @@ -294,6 +294,7 @@ enum asr_state { ASR_STATE_HALT, }; +#define MAXPACKETSZ 4096 __BEGIN_HIDDEN_DECLS @@ -301,6 +302,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); 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: lib/libc/asr/asr_run.3 =================================================================== RCS file: /d/cvs/src/lib/libc/asr/asr_run.3,v retrieving revision 1.2 diff -u -p -r1.2 asr_run.3 --- lib/libc/asr/asr_run.3 26 Mar 2014 18:13:15 -0000 1.2 +++ lib/libc/asr/asr_run.3 18 Feb 2017 14:39:22 -0000 @@ -314,6 +314,3 @@ so sharing a resolver among threads is n .Xr getrrsetbyname 3 , .Xr res_send 3 , .Xr resolv.conf 5 -.Sh CAVEATS -This DNS resolver implementation doesn't support -the EDNS0 protocol extension yet. Index: lib/libc/asr/asr_utils.c =================================================================== RCS file: /d/cvs/src/lib/libc/asr/asr_utils.c,v retrieving revision 1.14 diff -u -p -r1.14 asr_utils.c --- lib/libc/asr/asr_utils.c 17 Feb 2017 22:24:45 -0000 1.14 +++ lib/libc/asr/asr_utils.c 18 Feb 2017 10:44:23 -0000 @@ -381,6 +381,14 @@ pack_u16(struct asr_pack *p, uint16_t v) } static int +pack_u32(struct asr_pack *p, uint32_t v) +{ + v = htonl(v); + + return (pack_data(p, &v, 4)); +} + +static int pack_dname(struct asr_pack *p, const char *dname) { /* dname compression would be nice to have here. @@ -410,6 +418,18 @@ _asr_pack_query(struct asr_pack *p, uint pack_dname(p, dname); pack_u16(p, type); pack_u16(p, class); + + return (p->err) ? (-1) : (0); +} + +int +_asr_pack_edns0(struct asr_pack *p, uint16_t pktsz) +{ + pack_dname(p, ""); /* root */ + pack_u16(p, 41); /* OPT */ + pack_u16(p, pktsz); /* UDP payload size */ + pack_u32(p, 0); /* extended RCODE and flags */ + pack_u16(p, 0); /* RDATA len */ return (p->err) ? (-1) : (0); } Index: lib/libc/asr/res_mkquery.c =================================================================== RCS file: /d/cvs/src/lib/libc/asr/res_mkquery.c,v retrieving revision 1.9 diff -u -p -r1.9 res_mkquery.c --- lib/libc/asr/res_mkquery.c 9 Sep 2015 15:49:34 -0000 1.9 +++ lib/libc/asr/res_mkquery.c 18 Feb 2017 10:45:47 -0000 @@ -61,10 +61,14 @@ 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) + 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); _asr_ctx_unref(ac); Index: lib/libc/asr/res_send_async.c =================================================================== RCS file: /d/cvs/src/lib/libc/asr/res_send_async.c,v retrieving revision 1.30 diff -u -p -r1.30 res_send_async.c --- lib/libc/asr/res_send_async.c 17 Feb 2017 00:29:22 -0000 1.30 +++ lib/libc/asr/res_send_async.c 18 Feb 2017 10:45:16 -0000 @@ -377,10 +377,14 @@ 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) + 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 (p.err) { DPRINT("error packing query"); errno = EINVAL; @@ -448,8 +452,6 @@ udp_recv(struct asr_query *as) { ssize_t n; int save_errno; - -#define MAXPACKETSZ 4096 if (ensure_ibuf(as, MAXPACKETSZ) == -1) { save_errno = errno; Index: lib/libc/net/resolver.3 =================================================================== RCS file: /d/cvs/src/lib/libc/net/resolver.3,v retrieving revision 1.35 diff -u -p -r1.35 resolver.3 --- lib/libc/net/resolver.3 24 Jan 2017 12:43:00 -0000 1.35 +++ lib/libc/net/resolver.3 18 Feb 2017 14:37:06 -0000 @@ -193,9 +193,8 @@ allowing them to take advantage of a non and thus to send larger replies. DNS query packets with the EDNS0 extension are not compatible with non-EDNS0 DNS servers. -On .Ox -this option does nothing. +uses 4096 bytes as input buffer size. .It Dv RES_USE_DNSSEC Request that the resolver uses Domain Name System Security Extensions (DNSSEC), -- jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF DDCC 0DFA 74AE 1524 E7EE