On Thu, Dec 17, 2020 at 11:10:59AM +0100, Otto Moerbeek wrote: > On Thu, Dec 17, 2020 at 12:27:00AM -0800, Jordan Geoghegan wrote: > > > > > > > On 12/16/20 11:19 PM, Otto Moerbeek wrote: > > > On Wed, Dec 16, 2020 at 02:37:19PM -0800, Jordan Geoghegan wrote: > > > > > > > Hi folks, > > > > > > > > I've found some surprising behaviour in the 'dig' utility. I've noticed > > > > that > > > > dig doesn't seem to support link local IPv6 addresses. I've got unbound > > > > listening on a link local IPv6 address on my router and all queries > > > > seem to > > > > be working. I'm advertising this DNS info with rad, and I confirmed with > > > > tcpdump that my devices such as iPhones, Macs, Windows, Linux desktops > > > > etc > > > > are all properly querying my unbound server over IPv6. > > > > > > > > dhclient doesn't seem to allow you to specify an IPv6 address in it's > > > > 'supersede' options, so I manually edited my OpenBSD desktops > > > > resolv.conf > > > > to specify the IPv6 unbound server first. Again, I confirmed with > > > > tcpdump > > > > that my desktop was properly querying the unbound server over IPv6 (ie > > > > Firefox, ping, ssh etc all resolved domains using this server). > > > > > > > > I used 'dig' to make a query, and I noticed it was ignoring my link > > > > local > > > > IPv6 nameserver in my resolv.conf. I'll save you guys the long form Ted > > > > talk > > > > here and just make my point: > > > > > > > > $ cat resolv.conf > > > > nameserver fe80::f29f:c2ff:fe17:b8b2%em0 > > > > nameserver 2606:4700:4700::1111 > > > > lookup file bind > > > > family inet6 inet4 > > > > > > > > $ dig google.ca > > > > [snip] > > > > ;; Query time: 12 msec > > > > ;; SERVER: 2606:4700:4700::1111#53(2606:4700:4700::1111) > > > > [snip] > > > > > > > > There's a bit of a delay as it waits for a time out, and then it falls > > > > back > > > > to the cloudflare IPv6 server. > > > > > > > > I tried specifying the server with '@' as well as specifying source > > > > IP/interface with '-I' to no avail. It seems dig really doesn't like the > > > > 'fe80::%em0' notation, as '@' and '-I' worked fine when used without a > > > > link-local address. > > > > > > > > Is this a bug or a feature? Am I just doing something stupid? Any > > > > insight > > > > would be appreciated. > > > I think it is a bug and I can reproduce. Will invesigate deeper later. > > > > > > -Otto > > > > > > > Hi Otto, > > > > Thanks for looking into this! I took Bodie's advice and tested nslookup and > > host, and they both seem to have the same behaviour as dig. > > > > Regards, > > > > Jordan > > > > That is no big surprise, as they are essentially the same program > with a different user interface, all built from the same source. > > -Otto >
Fix below, further discussion on tech@ -Otto Index: dig.c =================================================================== RCS file: /cvs/src/usr.bin/dig/dig.c,v retrieving revision 1.18 diff -u -p -r1.18 dig.c --- dig.c 15 Sep 2020 11:47:42 -0000 1.18 +++ dig.c 17 Dec 2020 11:06:49 -0000 @@ -1358,7 +1358,7 @@ dash_option(char *option, char *next, di } else srcport = 0; if (have_ipv6 && inet_pton(AF_INET6, value, &in6) == 1) - isc_sockaddr_fromin6(&bind_address, &in6, srcport); + isc_sockaddr_fromin6(&bind_address, &in6, srcport, 0); else if (have_ipv4 && inet_pton(AF_INET, value, &in4) == 1) isc_sockaddr_fromin(&bind_address, &in4, srcport); else Index: dighost.c =================================================================== RCS file: /cvs/src/usr.bin/dig/dighost.c,v retrieving revision 1.34 diff -u -p -r1.34 dighost.c --- dighost.c 15 Sep 2020 11:47:42 -0000 1.34 +++ dighost.c 17 Dec 2020 11:06:49 -0000 @@ -540,7 +540,7 @@ get_addresses(const char *hostname, in_p struct sockaddr_in6 *sin6; sin6 = (struct sockaddr_in6 *)tmpai->ai_addr; isc_sockaddr_fromin6(&addrs[i], &sin6->sin6_addr, - dstport); + dstport, sin6->sin6_scope_id); } i++; @@ -972,7 +972,7 @@ parse_netprefix(struct sockaddr_storage if (inet_pton(AF_INET6, buf, &in6) == 1) { parsed = 1; - isc_sockaddr_fromin6(sa, &in6, 0); + isc_sockaddr_fromin6(sa, &in6, 0, 0); if (prefix_length > 128) prefix_length = 128; } else if (inet_pton(AF_INET, buf, &in4) == 1) { Index: lib/isc/sockaddr.c =================================================================== RCS file: /cvs/src/usr.bin/dig/lib/isc/sockaddr.c,v retrieving revision 1.14 diff -u -p -r1.14 sockaddr.c --- lib/isc/sockaddr.c 28 Nov 2020 06:33:55 -0000 1.14 +++ lib/isc/sockaddr.c 17 Dec 2020 11:06:49 -0000 @@ -223,7 +223,7 @@ isc_sockaddr_anyofpf(struct sockaddr_sto void isc_sockaddr_fromin6(struct sockaddr_storage *sockaddr, const struct in6_addr *ina6, - in_port_t port) + in_port_t port, uint32_t scope) { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sockaddr; memset(sockaddr, 0, sizeof(*sockaddr)); @@ -231,6 +231,7 @@ isc_sockaddr_fromin6(struct sockaddr_sto sin6->sin6_len = sizeof(*sin6); sin6->sin6_addr = *ina6; sin6->sin6_port = htons(port); + sin6->sin6_scope_id = scope; } int Index: lib/isc/include/isc/sockaddr.h =================================================================== RCS file: /cvs/src/usr.bin/dig/lib/isc/include/isc/sockaddr.h,v retrieving revision 1.7 diff -u -p -r1.7 sockaddr.h --- lib/isc/include/isc/sockaddr.h 15 Sep 2020 11:47:42 -0000 1.7 +++ lib/isc/include/isc/sockaddr.h 17 Dec 2020 11:06:49 -0000 @@ -91,7 +91,7 @@ isc_sockaddr_fromin(struct sockaddr_stor void isc_sockaddr_fromin6(struct sockaddr_storage *sockaddr, const struct in6_addr *ina6, - in_port_t port); + in_port_t port, uint32_t scope); /*%< * Construct an struct sockaddr_storage from an IPv6 address and port. */ Index: lib/lwres/lwconfig.c =================================================================== RCS file: /cvs/src/usr.bin/dig/lib/lwres/lwconfig.c,v retrieving revision 1.6 diff -u -p -r1.6 lwconfig.c --- lib/lwres/lwconfig.c 25 Feb 2020 05:00:43 -0000 1.6 +++ lib/lwres/lwconfig.c 17 Dec 2020 11:06:49 -0000 @@ -231,7 +231,7 @@ lwres_conf_parsenameserver(lwres_conf_t res = lwres_create_addr(word, &address, 1); use_ipv4 = confdata->flags & LWRES_USEIPV4; - use_ipv6 = confdata->flags & LWRES_USEIPV4; + use_ipv6 = confdata->flags & LWRES_USEIPV6; if (res == LWRES_R_SUCCESS && ((address.family == LWRES_ADDRTYPE_V4 && use_ipv4) || (address.family == LWRES_ADDRTYPE_V6 && use_ipv6))) {