Subject: Re: re-reading /etc/resolv.conf on change
To: NetBSD Userlevel Technical Discussion List <tech-userlevel@NetBSD.ORG>
From: mouss <usebsd@free.fr>
List: tech-userlevel
Date: 01/04/2004 17:52:20
Greg A. Woods wrote:
> 
> No, it's not "silly" at all.
> 
> Hacking on the NetBSD resolver "fixes" the problem for a tiny percentage
> of real users in the world.  In the mean time the problem remains for
> all DNS-using applications on all other platforms.  Now that's silly.

ahem... Can you show me a change in the netbsd sources that solved 
problems for real users in the world? Sure there are, but at the time 
they were implemented in netbsd, they weren't available to other users. 
And this is similar to the current issue. If a good solution is 
implemented by netbsd, then it may be imported by others.

> 
> The only _right_ place to "fix" this problem is in the applications.
> All portable applications _must_ deal with this issue directly on their
> own anyway, if they care to.

No, at start, the resolver library was written so that applications 
don't have to deal with the name system. Otherwise, let every app 
implement DNS and let's get rid of the resolver. Actually, when a 
problem is to be solved in at least two applications, then the right 
solution is almost always to solve it in a library. Otherwise, fixing 
every application when a problem is found is just anti-productive.

> 
> If you really want to try to fix the resolver then please propose your
> change _first_ to ISC and see if maybe they think it might be a good
> idea.  Then if they do they can choose to implement it and then IFF they
> choose to do so "we" can incorporate _their_ final design solution into
> the NetBSD resolver IFF "we" think it'll take too long to get their
> actual implementation incorporated into NetBSD.

I understand the concern that changes in the resolver will make it 
harder to integrate the next version. However, the resolver has already 
been modified.

> 
> Meanwhile all DNS-using applications will continue to have to deal with
> this issue until the vast majority of installed resolver implementations
> universally deal with it for them.

So what? Should we stay bug-compatible? After all, these people don't 
care about the problems we have, why should I care about theirs?
Also the majority of the running systems don't have this problem, as 
they run windows!

> 
> As already pointed out the problems with using a local caching resolver
> do not apply to anyone running the likes of Mozilla!
> 

Mozilla was just an example. Proxies running on a firewall are another. 
Do you want to force firewalls to run a name server?


> 
> Then fix those tools -- they are broken.  The fixes are pretty trivial
> too since the job that needs doing is almost exactly the same as the one
> they already do.

Your own argument (submitting fixes to ISC) applies here, except that 
we'll have a lot of fixes to submit to a lot of people, and given the 
debate here, it is clear that this will bring endless discussions...

> 
> Yes of course.  They already do and all portable applications _must_ do
> so!
> 

Mozilla is portable and doesn't do so:)

> And it's not a hack -- it's simply proper use of an existing well known
> API designed for this very purpose (though sadly it has not been as
> clearly documented as being usable for this purpose as it should have
> been, even though it has been usable for this purpose for well over a
> decade now).

No. What you're proposing (from my understanding) is that one 
application (dhclient or whatever) send a signal to N applications (N 
may be large), so as they call res_init() again.
This in turn requires apps to register with dhclient (or with something 
else) saying "I wanna know when foo changes". A simpler approach is to 
reboot.

Also, most daemons use sighup to reload their own config file. What you 
are proposing is that they reload everything when resolv.conf changes 
(because signals don't carry data, so the app doesn't know why she's 
signalled). In some cases, this means the overhead of rebuilding their 
internal data structures ("recompiling the config file"), just because 
of a resolv.conf change...

Add to this that those fork-on-accept daemons don't need to reload their 
conf (older sessions use old config) except in the root process. In the 
resolver case, even the children need to reload resolv.conf (via the 
resolver). So you're proposing that they handle sighup (or other) and 
check whether they are a child or a root process, ... etc. Welcome to a 
spaghetti world?

The resolver lib has always been here to hide the DNS details, and 
should continue to do so. Applications should not even care about which 
resolution system is used, so that if someday DNS is replaced with 
something else, we won't need to fix all those apps.


> 
> Well the difference in behaviour is necessary to match the particular
> needs of each application, though ultimately the differences will be
> minor and for the most part invisible to the end user.
> 

If the system doesn't help application developpers, then they'll 
continue to reinvent the wheel, and that is not invisible to the end 
user, as it generally results in a lot of problems.

> For the most part the obvious way for any application to safely deal
> with this issue without having to know any system specific details (such
> as the pathname of the resolver configuration file) is to simply retry
> failed gethost*() lookups after calling res_init() (or res_ninit() for
> thread safety, or their equivalent in non-BIND resolver APIs) and only
> return an error if the second try also fails.
> 

What if gethost* succeeds, with incorrect results?
Why make life harder for application developpers when this can all be 
encapsulated in a library that's sole purpose is to help in name resolution?
compare:
	...
	gethost*()
	if (error) {
		error("failed to get it")
		back to where you came from
	}
	...
with
	...
	gethost*()
	if (error) {
	#if MT
		res_ninit()
	#else
		res_init()
	#endif
		if (error) {
			err("res_xinit failed ....)
			break/goto where you came from
		}
		gethost*(); /* again */
	}
	if (error) {
		error("failed to get it")
		back to where you came from
	}
	...

I really prefer to have the latter in a single place than in a lot of apps.



regards,
mouss