Bugzilla – Bug 3431
DNS resolution not working on some Windows systems
Last modified: 2008-09-15 14:38:25 UTC
First a quote from the Net::DNS::Resolver manpage: "On UNIX systems the defaults are read from the following files, in the order indicated: /etc/resolv.conf $HOME/.resolv.conf ./.resolv.conf [...] On Windows systems, an attempt is made to determine the system defaults using the registry. This is still a work in progress; systems with many dynamically configured network interfaces may confuse Net::DNS." I have exactly this problem on my system. All attempts to access any internet resources from slimserver result in a DNS error. I was able to solve this by specifying a nameserver explicitely in Slim::Networking::AsyncHTTP::new(): my $resolver = Net::DNS::Resolver->new(nameservers => [qw(192.168.1.253)]); I think we should at least have a configuration option for manually specifying nameservers - which is still not very userfriendly for people with affected systems. However before the new AsyncHTTP code in 6.3 was introduced, there was never a problem with DNS. So maybe there is another solution. I have put "Severity" to "critical" because I think this problem can be very annoying to the novice user, if it occurs. It breaks a lot of functionality.
Good find, you are right we need to find a way around this. It used to work because it used the system resolver libraries (which block). I wonder if any of the Win32 modules can find the current DNS server...
Upgraded Net::DNS to 0.57 in both 6.3 and 6.5. Several win32-related fixes were made that should help, especially on XP with DHCP. If tonight's nightly still has problems, please reopen. More info: https://rt.cpan.org/Public/Bug/Display.html?id=11931
I checked out the Subversion changes and the problem still appears on my system. I also found the problem, causing the DNS resolution to fail. Net::DNS::Resolver::Base::bgsend() only uses the first DNS server from the DNS servers list. When a network interface with a DNS server is not active and it is the first in the list, the DNS resolution will fail. I have this situation, since I have VPN interfaces that are not connected all the time. In contrast send_tcp() uses all nameservers. This is a bug in Net::DNS, I think.
Having a primary DNS server that isn't valid is probably a bad idea and certainly can't be a common setup. Shouldn't your DNS server list change dynamically when you connect to your VPN? That's how my VPN connections have always worked. In the RT discussion there's a link to some SpamAssassin code that works around this issue. I think we can steal some of that code. Bumping sev down to normal as this won't affect very many people.
(In reply to comment #4) > Having a primary DNS server that isn't valid is probably a bad idea and > certainly can't be a common setup. Shouldn't your DNS server list change > dynamically when you connect to your VPN? It seems to be a problem of how Net::DNS retrieves the server list from the registry. I have no control over which is the primary DNS server. It just takes the first DNS server that appears in the registry. So it even takes DNS servers from interfaces that are down. > In the RT discussion there's a link to some SpamAssassin code that works around > this issue. I think we can steal some of that code. Will have a look into this. > Bumping sev down to normal as this won't affect very many people. Ok. Would have proposed that anyway ;)
Ah, I misunderstood. I thought it was pulling them in order but you had an invalid one set as your primary DNS.
Created attachment 1245 [details] send udp to all nameservers (bgsend) This patch changes bgsend in a way that it sends UDP requests to all nameservers that share the same socket type as the first nameserver. The first answer is taken. Solves the problem - but not the elegant way.
Can you post your patch to RT to see what the maintainer thinks? My idea is to query all nameservers at startup-time to build a list of valid NS's that can be used for all async queries.
(In reply to comment #8) > Can you post your patch to RT to see what the maintainer thinks? I am currently looking into a better way to find disabled network devices or use the TCP linkage information form the registry. I have a bad feeling about the patch because it fixes a Win32-issue in platform independent code. However I will ask at RT what they think about it. > My idea is to query all nameservers at startup-time to build a list of valid > NS's that can be used for all async queries. I think that is the way the ppl at SpamAssassin do it. Seems a better approach to me.
Created attachment 1246 [details] recognize nameservice order under win2k/xp This patch extracts the information about DNS search order from the registry and sorts the nameservers appropriately. AFAIR there is a UI option in Win2k/XP where to specify the global search order (not per interface). But I can't find it right away. Most of the time it should be right automatically. Will submit this patch to RT discussion, also.
Comment on attachment 1246 [details] recognize nameservice order under win2k/xp Index: G:/Programme/SlimServer/server/CPAN/Net/DNS/Resolver/Win32.pm =================================================================== --- G:/Programme/SlimServer/server/CPAN/Net/DNS/Resolver/Win32.pm (revision 7602) +++ G:/Programme/SlimServer/server/CPAN/Net/DNS/Resolver/Win32.pm (revision 7605) @@ -14,10 +14,15 @@ use Win32::Registry; sub init { + my ($class) = @_; my $defaults = $class->defaults; + # my $self = bless({ %{$class->defaults} }, $class); + # + # $self->{'debug'} = 1; + my ($resobj, %keys); my $root = 'SYSTEM\CurrentControlSet\Services\Tcpip\Parameters'; @@ -83,13 +88,33 @@ # } + my $bind_linkage; + my @sorted_interfaces; + print ";; DNS: Getting sorted interface list\n" if $self->{'debug'}; + $main::HKEY_LOCAL_MACHINE->Open('SYSTEM\CurrentControlSet\Services\Tcpip\Linkage', + $bind_linkage); + if($bind_linkage){ + my $bind_linkage_list; + my $type; + $bind_linkage->QueryValueEx('Bind', $type, $bind_linkage_list); + if($bind_linkage_list){ + @sorted_interfaces = split(m/[^\w{}\\-]+/s, $bind_linkage_list); + } + foreach my $interface (@sorted_interfaces){ + $interface =~ s/^\\device\\//i; + print ";; DNS:Interface: $interface\n" if $self->{'debug'}; + } + } - my $interfaces; $resobj->Open("Interfaces", $interfaces); if ($interfaces) { my @ifacelist; - $interfaces->GetKeys(\@ifacelist); + if(@sorted_interfaces){ + @ifacelist = @sorted_interfaces; + }else{ + $interfaces->GetKeys(\@ifacelist); + } foreach my $iface (@ifacelist) { my $regiface; $interfaces->Open($iface, $regiface);
Created attachment 1247 [details] recognize nameservice order (right patch) sorry, I submitted the wrong patch. Was also a bit confused about the "edit attachment as comment" option. Sorry about the mess - here is the right patch.
I haven't tested your patch, but I manually added 3 nameservers to my main interface, and they show up in the registry as a comma-separated list at Tcpip/Parameters/Interfaces/$GUID/NameServer. I have XP SP2 by the way. All 3 servers are also found by Net::DNS::Resolver::Win32 and are in the correct order. So that brings us back to the problem that bgsend only uses the first one.
I've committed a patch that checks for a working nameserver at startup. Please test.
http://svn.slimdevices.com/trunk/server/Slim/Networking/AsyncHTTP.pm?rev=7474&view=diff&r1=7474&r2=7473&p1=trunk/server/Slim/Networking/AsyncHTTP.pm&p2=/trunk/server/Slim/Networking/AsyncHTTP.pm
(In reply to comment #13) > All 3 servers are also found by Net::DNS::Resolver::Win32 and are in the > correct order. Yes, the order is correct, when you use multiple dns servers on ONE interface, however as windows stores the nameservers per interface, the current code just takes the nameservers from MULTIPLE interfaces in the order, the interfaces appear in the registry. (sorted by GUID) The patch also recognizes the order of the tcpip\Linkage\Bind entries that specifies the order in which several interfaces should be tried. Your change looks good - I will give it a try. But I think, the nameservice order patch should be applied, also. As the user can specify a nameservice order on other operating systems, this should also be the case for Win32. But maybe this will make it into CPAN.
It works with your patch. However without the "nameservice order patch" the server takes longer to start - because of the first nameserver timing out. I just saw that the line # my $self = bless({ %{$class->defaults} }, $class); in my patch should not be commented out. The variable $self will be missing later.
Marking closed. When you get your patch applied upstream (Net::DNS), remind me, and we'll use it.
(In reply to comment #18) > Marking closed. When you get your patch applied upstream (Net::DNS), remind > me, and we'll use it. According to Olaf Kolkman, the Patch is now applied to the trunk (Net::DNS). I have also sent a patch to the author of Win32::IPHelper with the necessary function to get the Dns Servers directly from the windows api - which may be a much better approach. So keep watching Net::DNS, as it might use it. (Usage of GetNetworkParams() was discussed on RT/CPAN)