wahern / dns

dns.c: Single file non-blocking DNS C library without callbacks or external dependencies.
http://25thandclement.com/~william/projects/dns.c.html
MIT License
256 stars 64 forks source link

Default to 127.0.0.1 when /etc/resolv.conf missing #7

Closed wahern closed 8 years ago

wahern commented 8 years ago

The current code initializes struct dns_resolv_conf with a default name server of 0.0.0.0. However, that's only half of the original BIND semantics. 0.0.0.0 should be translated to 127.0.0.1 when finalizing the list, which in our case means when copying the name servers into the hints database. The translation should happen in either dns_hints_insert_resconf, or dns_hints_insert. The former is probably safer; the latter has its own appeal, but might be a tad too magical.

This should resolve issues received by the Enlightenment team where broken systems fail to write-out /etc/resolv.conf, yet applications using gethostbyname(3) or getaddrinfo(3) still work when a local DNS proxy is running.

Here's the relevant bits from glibc 2.23:

/*
 * Resolver state default settings.
 */

/*
 * Set up default settings.  If the configuration file exist, the values
 * there will have precedence.  Otherwise, the server address is set to
 * INADDR_ANY and the default domain name comes from the gethostname().
 *
 * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
 * rather than INADDR_ANY ("0.0.0.0") as the default name server address
 * since it was noted that INADDR_ANY actually meant ``the first interface
 * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
 * it had to be "up" in order for you to reach your own name server.  It
 * was later decided that since the recommended practice is to always
 * install local static routes through 127.0.0.1 for all your network
 * interfaces, that we could solve this problem without a code change.
 *
 * The configuration file should always be used, since it is the only way
 * to specify a default domain.  If you are running a server on your local
 * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
 * in the configuration file.
 *
 * Return 0 if completes successfully, -1 on error
 */

and

        if (__builtin_expect(statp->nscount == 0, 0)) {
            statp->nsaddr.sin_addr = __inet_makeaddr(IN_LOOPBACKNET, 1);
            statp->nsaddr.sin_family = AF_INET;
            statp->nsaddr.sin_port = htons(NAMESERVER_PORT);
            statp->nscount = 1;
        }