On 2024-02-15 10:56, Jim Garrison via Cygwin wrote:
On 2/14/2024 17:08, Brian Inglis via Cygwin wrote:
On 2024-02-14 16:28, Jim Garrison via Cygwin wrote:
Win 11 Cygwin "dig" and "host": Option -6 causes command to hang

Ditto!

Without IPv6 nameservers in /etc/resolv.conf I get:

$ host -6 google.com
;; connection timed out; no servers could be reached
Failing assertion due to probable leaked memory in context 0xa00020be0 ("dig") (stats[4].gets == 1).
mem.c:1121: INSIST(ctx->stats[i].gets == 0U) failed.

but with IPv6 nameservers in /etc/resolv.conf I get:

$ host -6 google.com
google.com has address 142.251.211.238
google.com has IPv6 address 2607:f8b0:400a:804::200e
google.com mail is handled by 10 smtp.google.com.

I added a Cygwin postinstall script:

     /etc/postinstall/0p_l_etc_resolv_conf.dash

to create resolv.conf from `ipconfig /all` DNS servers, an internal list of open public DNS servers, and search domains, update:

     /var/run/resolvconf/resolv.conf

when changed, and `ln -frsvt /etc/`, also run from a Scheduled Task on System Restart.

Unfortunately, this is only a partial solution because your delegated prefix can change if your ISP changes it.  The firewall knows how to track this, and will issue a new LAN IP address at the next lease expiration.  But, the firewall is also providing name resolution, and after its LAN prefix changes (and the grace period expires) Cygwin's name resolultion would be left pointing to a non-existent address.

That is why I run the resolv.conf postinstall script to check and change /etc/resolv.conf near the start of Cygwin Setup postinstall, and after Windows restart. You can set up the cron daemon or Scheduled Tasks to do this whenever you need, or if you run a change detection script, it could do so: it only changes the installed file if the generated file contents differ.

Also, IPv4 resolution does not seem to depend on resolv.conf, and Windows clearly does not depend on resolv.conf for either IPv4 or IPv6. Maybe Cygwin should just ask Windows for the name servers?

That's what my resolv.conf setup script does with Windows `ipconfig /all` 
output.

As a counterpoint I note that on dual stack Linux one DOES need an extra daemon (resolvconf or systemd-resolved) to manage merging of IPv4 and IPv6 DHCP configurations.  Without one of those, the IPv6 client overwrites the resolv.conf created by the IPv4 client.

That's why I create /var/run/resolvconf/resolv.conf for compatibility then symlink to /etc/resolv.conf (and my /var/run is a compatibility symlink to /run/).

Maybe Cygwin needs the equivalent of resolvconf?  I found references to a file called resolvconf in the sources/devel packages for unbound, but unbound itself doesn't seem to contain anything with that name. Also unbound seems to be currently unmaintained.

Windows does not discriminate between IP v4 and v6 DNS name servers, but unfortunately Cygwin does not support a/hosts/v4/v6 enumeration.

Have a look at the attached scripts, try them out on your system, and adapt them to do what you want with them: treat them as Public Domain; they have some tweaks to support some open public DNS name servers as backups for my ISP's, and tweaks for that ISP and my preferences, but unsure if "search" list suffixes work or affect anything?

--
Take care. Thanks, Brian Inglis              Calgary, Alberta, Canada

La perfection est atteinte                   Perfection is achieved
non pas lorsqu'il n'y a plus rien à ajouter  not when there is no more to add
mais lorsqu'il n'y a plus rien à retirer     but when there is no more to cut
                                -- Antoine de Saint-Exupéry
#!/usr/bin/awk -f
# cyg-resolv.awk - create Cygwin resolv.conf from Windows ipconfig /all output

BEGIN {
# ISP domains
    isp_domains = "shaw[^.]*[.]|sjrb[.]"
    isp         = "shaw.ca."
# suffixes
    SUF  = "ca. uk. org. com. net. edu."
# public name servers Quad 9, Cloudflare, Open DNS, Google, Comodo
    NS          = "dns.quad9.net. one.one.one.one. "                    \
                "resolver2.opendns.com. resolver1.opendns.com. "        \
                "google-public-dns-b.google.com. 
google-public-dns-a.google.com. " \
                "ns2.recursive.dnsbycomodo.com. ns1.recursive.dnsbycomodo.com. 
"   \
                ""
# CleanBrowsing
#           "security-filter-dns.cleanbrowsing.org. "                   \
#           "adult-filter-dns.cleanbrowsing.org. "                      \
#           "family-filter-dns.cleanbrowsing.org. "                     \
# CIRA Canadian Shield Protected+malware+phishing
#           "CAshieldProtected"                                         \
# resolv.conf comments
    CFHD = "# /etc/resolv.conf"
    CFHD = CFHD " - Internet Domain Name System resolver configuration file"
    CDS  = "# domain suffix"
    CSSL = "# suffix search list"
# hosts command
    hosts = "/usr/bin/getent ahosts"
# IP v4
    # digit patterns: [0-9], [1-9], [6-9], [0-4], [0-5], [0[0]]0-255, 
.[0[0]]0-255, .[0]16-31
    z9          = "[0-9]"
    o9          = "[1-9]"
    s9          = "[6-9]"
    z4          = "[0-4]"
    z5          = "[0-5]"
    p0_255      = "(0{0,2}" z9 "|0{0,1}" o9 z9 "|1" z9 z9 "|2(" z4 z9 "|5" z5 
"))"
    d0_255      = "(." p0_255 ")"
    d16_31      = ".0?(1" s9 "|2" z9 "|3[01])"
    ipv4        = "^" p0_255 d0_255 "{3}$"
# private subnets
    # 10.0.0.0-.255.255.255
    p10         = "^10" d0_255 "{3}$"
    # 169.254.0.0-.255.255 Zeroconf Link-Local (IPv4LL) Automatic Private IP 
Addressing (APIPA) 
    p169        = "^169.254" d0_255 "{2}$"
    # 172.16.0.0-.31.255.255
    p172        = "^172" d16_31 d0_255 "{2}$"
    # 192.168.0.0-.255.255
    p192        = "^192.168" d0_255 "{2}$"
# IP v6
    # hex, id
    px          = "[0-9A-Fa-f]"
    gx          = px "{0,4}"
    cx          = ":" gx
    id          = "[0-9A-Za-z]"
    ipv6        = "^" gx "(" cx "){1,7}" "(%" id "+)?$"
# private subnets
    # fc00::/7  fc-fe + ff bit 7 local
    pfc00       = "^[Ff][C-Fc-f]" px "{2}:"
# seen to avoid duplication
    used["127.0.0.1"] = "127.0.0.1"
}


function nextaddr( addr, name, ns, nameserveraddr, nameserverhostname   
,private,n) {
    if (DEBUG) print addr, name, ns > DEBUG

    # private subnets
    if (!(addr in used || addr ~ p10 || addr ~ p169 || addr ~ p172 || addr ~ 
p192 || addr ~ pfc00)) {
        n = ++ns

        if (addr)   { nameserveraddr[n] = addr }

        if (name)   { nameserverhostname[n] = name }

        if (DEBUG) print addr, name, ns > DEBUG

        used[addr] = addr
    }

    return ns
}


function addrs( NS, nameserveraddr, ns  ,c) {
# $ getent ahosts $NS
# 1.0.0.1         STREAM      one.one.one.one
# 1.0.0.1         DGRAM       one.one.one.one
# 1.1.1.1         STREAM
# 1.1.1.1         DGRAM
# 149.112.112.112 0      dns.quad9.net
# 9.9.9.9         0
# 208.67.220.220  0      resolver2.opendns.com
# 208.67.222.222  0      resolver1.opendns.com
# 8.8.4.4         0      google-public-dns-b.google.com
# 8.8.8.8         0      google-public-dns-a.google.com
# 149.112.122.20  0      CAshieldProtected      
# 149.112.121.20  0
    c = hosts " " NS

    while ((c | getline) > 0) {
            ns = nextaddr( $1, $3, ns, nameserveraddr, nameserverhostname)
    }

    close( c )

    return ns
}


/\r/                            { sub( /\r/, "", $NF) } # trim \r


# collect DNS domain suffixes
/D[Nn][Ss]\sSuffix[^:]*:\s\S/   {
    last = $NF
    if (last ~ /\./ && last !~ /\.$/)   last = last ".";        # add root dot

    if (!(last in domain)) {
        domain[last] = last
        domains = domains " " last
    }

    while (last ~ /\..+\..+/) { # strip labels if more than two for domain
        sub(/^[^.]+./, "", last)
        if (last ~ /\./ && last !~ /\.$/)       last = last "."; # add root dot

        if (!(last in domain)) {
            domain[last] = last
            domains = domains " " last
        }
    }
}


# collect DNS search suffixes
/Search\sList[^:]*:\s\S/        {
    for (d in domain) {
        if (!(d in search))     search[d] = d

        if (d ~ isp_domains) {
            last = isp

            if (!(last in search)) {
                search[last] = last
                domains = domains " " last
            }
        }
    }

    last = $NF
    if (last ~ /\./ && last !~ /\.$/)   last = last ".";        # add root dot

    if (!(last in search)) {
        search[last] = last
        domains = domains " " last
    }

    while (last ~ /\..+\..+/) { # strip labels if more than two for domain
        sub(/^[^.]+./, "", last)
        if (last ~ /\./ && last !~ /\.$/)       last = last "."; # add root dot

        if (!(last in search)) {
            search[last] = last
            domains = domains " " last
        }
    }

    ns = split( SUF, sa)

    for (s = 1; s <= ns; ++s) {
        last = sa[s]
        if (last ~ /\./ && last !~ /\.$/)       last = last "."; # add root dot

        if (!(last in search)) {
            search[last] = last
            domains = domains " " last
        }
    }
}


# collect DNS server IP addresses
/DNS\sServers[^:]*:\s\S/                { dns = 1 }     # start - enable


dns && ($NF ~ ipv4 || $NF ~ ipv6)       {               # collect IP addrs
    ns = nextaddr( $NF, last, ns, nameserveraddr, nameserverhostname)
    last = ""
}


dns && $NF !~ ipv6 && $NF !~ ipv4       { dns = 0 }     # non-IP disable


# output unique resolv.conf entries
END {
    print CFHD

    ns = addrs( NS, nameserveraddr, ns)

    for (n = 0; n <= ns; ++n)   {
        if (n in nameserverhostname && nameserverhostname[n]) {
            print "#", nameserverhostname[n]
        }

        if (n in nameserveraddr && nameserveraddr[n]) {
            print "nameserver", nameserveraddr[n]
        }
    }

    print CDS

    for (d in domain)           { print "domain " d }

    print CSSL
    if (domains)        print "search" domains
}

#!/bin/dash
# 0p_l_etc_resolv_conf.dash - update /etc/resolv.conf if changed

r=resolv
cr=/usr/local/bin/cyg-$r.awk
run=/var/run/${r}conf
rrc=$run/$r.conf
SYSCONFDIR=${SYSCONFDIR:-/etc}
conf=$SYSCONFDIR/$r.conf

/bin/mkdir -pv          -- $run/                && \
ip=$(/usr/bin/which     -- ipconfig)            && \
tmp=$(/bin/mktemp -t    -- .XXXXXXXX.)          && \
$ip /all | $cr   > $tmp                         && \
[ -s $tmp ]                                     && \
[ -w $rrc ]     || : > $rrc
if ! /usr/bin/cmp -s    -- $tmp $rrc; then
    /bin/cp -fv         -- $tmp $rrc
    /bin/ln -frsTv      -- $rrc $conf
fi

/bin/rm -f              -- $tmp
-- 
Problem reports:      https://cygwin.com/problems.html
FAQ:                  https://cygwin.com/faq/
Documentation:        https://cygwin.com/docs.html
Unsubscribe info:     https://cygwin.com/ml/#unsubscribe-simple

Reply via email to