Skip Menu |

This queue is for tickets about the Net-DNS CPAN distribution.

Report information
The Basics
Id: 13239
Status: resolved
Priority: 0/
Queue: Net-DNS

People
Owner: Nobody in particular
Requestors: vlada [...] devnull.cz
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: 0.48
Fixed in: 0.52



Subject: query() does not query all DNS servers in nameservers list
- FreeBSD system with port p5-Net-DNS-0.48 - FreeBSD version: 4.10-RELEASE-p5 FreeBSD cvs.xyz.cz 4.10-RELEASE-p5 FreeBSD 4.10-RELEASE-p5 #0: Thu Jan 27 16:46:11 CET 2005 root@cvs.xyz.cz:/usr/src/sys/compile/cvs.xyz.cz i386 query() function does not query all DNS in nameservers list in case it receives REFUSED answer. Consider following function: sub dns_find_addrs { my ($name) = @_; my @addrs = (); my $resolver = Net::DNS::Resolver->new; # print $resolver->nameservers; my $query = $resolver->query($name, 'ANY'); if ($query) { foreach my $rec ($query->answer) { if ($rec->type eq 'A' || $rec->type eq 'AAAA') { push @addrs, $rec->address; } elsif ($rec->type eq 'CNAME') { my $query = $resolver->query($rec->rdatastr, 'ANY'); if ($query) { foreach my $rec ($query->answer) { $rec->type eq 'A' || $rec->type eq 'AAAA' and push @addrs, $rec->address; } } else { warn "DNS CNAME-based query failed: ", $resolver->errorstring, "\n"; } } } } else { warn "DNS query failed: ", $resolver->errorstring, "\n"; } @addrs or warn "$name has no DNS records\n"; return @addrs; } When called on c12.xyz.cz and than on x3.xyz.cz, it behaves like this: 13:48:02.037179 DNSCLIENT.4481 > DNSSERVER.53: 10432+ ANY? c12.xyz.cz. (32) 13:48:02.037448 DNSSERVER.53 > DNSCLIENT.4481: 10432* 1/2/2 CNAME lo0.c12.xyz.cz. (117) 13:48:02.050795 DNSCLIENT.1319 > DNSSERVER.53: 10433+ ANY? lo0.c12.xyz.cz. (36) 13:48:02.051161 DNSSERVER.53 > DNSCLIENT.1319: 10433* 1/2/2 A 195.1.2.2 (119) 13:48:02.056622 DNSCLIENT.3457 > DNSSERVER.53: 10434+ ANY? x3.xyz.cz. (40) 13:48:02.057163 DNSSERVER.53 > DNSCLIENT.3457: 10434 Refused 0/0/0 (40) There are 3 DNS servers in the list, but after the first refuses to answer, the next 2 DNS servers are not queried.
Thanks for the extensive bug report. Fortunatelly there is probably nothing to fix as this problem should have been fixed in version 0.48_01. AFAIK the FreeBSD ports tree includes version 0.51. So a portupgrade should do. I will resolve the ticket. Please reopen it if your problem is not resolved. From the Changes file: *** 0.48_01 March 7, 2005 (Version 0.49 release candidate 1) Fix: rt.cpan.org #8882 No redundant lookups on SERVFAIL response and #6149 Does not search multiple DNS servers Net::DNS::Resolver will now use the other nameservers in the list if the RCODE of the answer is not NO ERROR (0) or NAME ERROR (3). When send() exhausted the last nameserver from the it will return the answer that was received from the last nameserver that responded with an RCODE. The error string will be set to "RCODE: <rcode from last packet>"
From: vlada [...] devnull.cz
[OLAF - Tue Jun 14 08:30:14 2005]: Show quoted text
> > > > Thanks for the extensive bug report. Fortunatelly there is probably > nothing to fix as this problem should have been fixed in version > 0.48_01. >
Good news, thanks. Show quoted text
> AFAIK the FreeBSD ports tree includes version 0.51. So a portupgrade > should do. >
I cannot upgrade to 0.51 right now, because this newer version requires Perl 5.6.0 (bytes.pm). Time to upgrade the system to FreeBSD 5.x with newer Perl..
Show quoted text
> > I cannot upgrade to 0.51 right now, because this newer version > requires > Perl 5.6.0 (bytes.pm). Time to upgrade the system to FreeBSD 5.x with > newer Perl.. >
Ouch.. I had not realized that introducing the bytes pragma would cause backwards compatable pains. Version 0.49_02 commes closest but that will probably bite you too because of AF_INET6 does not work with the use strict pragma. Go for 0.49 ... that should still work with an old perl and fix your problem. --Olaf
[OLAF - Tue Jun 14 08:59:21 2005]: Show quoted text
>
> > > > I cannot upgrade to 0.51 right now, because this newer version > > requires > > Perl 5.6.0 (bytes.pm). Time to upgrade the system to FreeBSD 5.x with > > newer Perl.. > >
> > > Ouch.. I had not realized that introducing the bytes pragma would cause > backwards compatable pains. > > Version 0.49_02 commes closest but that will probably bite you too > because of AF_INET6 does not work with the use strict pragma. > > Go for 0.49 ... that should still work with an old perl and fix your > problem. >
0.49 behaves better, but the problem is still present, although in smaller extent: 15:44:07.038939 DNSCLIENT.3106 > DNSSERVER_1.53: 39544+ ANY? c12.xyz.cz. (32) 15:44:07.039262 DNSSERVER_1.53 > DNSCLIENT.3106: 39544* 1/2/2 CNAME lo0.c12.xyz.cz. (117) 15:44:07.052658 DNSCLIENT.3846 > DNSSERVER_1.53: 39545+ ANY? lo0.c12.xyz.cz. (36) 15:44:07.052927 DNSSERVER_1.53 > DNSCLIENT.3846: 39545* 1/2/2 A 195.1.2.2 (119) 15:44:07.058599 DNSCLIENT.2442 > DNSSERVER_1.53: 39546+ ANY? x3.xyz.cz. (40) 15:44:07.059230 DNSSERVER_1.53 > DNSCLIENT.2442: 39546 Refused 0/0/0 (40) 15:44:07.060491 DNSCLIENT.2442 > DNSSERVER_3.53: 39546+ ANY? x3.xyz.cz. (40) 15:44:07.060871 DNSSERVER_3.53 > DNSCLIENT.2442: 39546 NXDomain* 0/1/0 (90) The /etc/resolv.conf looks like this: nameserver DNSSERVER_1 nameserver DNSSERVER_2 nameserver DNSSERVER_3 search hide.xyz.cz xyz.cz First two servers (DNSSERVER_1, DNSSERVER_2) have RFC 1918 IP addresses, the third have IP address from production range. All three DNS servers are specified by IPv4 addresses. It queries the first server (DNSSERVER_1) and after it receives REFUSED, it queries third server but skips the second server (which knows the answer) which results in unsuccessfull function call. I have double checked that the DNSSERVER_2 answers correctly via host(1) tool, so this is Net::DNS problem.
Show quoted text
> 0.49 behaves better, but the problem is still present, although in > smaller extent:
Thanks for testing! This is indeed still a bug. Its on my todo list. --Olaf
[OLAF - Tue Jun 14 10:37:21 2005]: So here is an approach... Somewhere in lib/Net/DNS/Resolver/Base we loop over an array of array references that contain information about the nameservers. If a nameserver fails to answer the array is rearanged. The bug is caused by shortening the array over which the foreach loop is performed. Instead of rearanging the @ns array within the foreach loop, wich makes us jump an index, we store the error code in $ns->[3]. If $ns->[3] is defined we take the next $ns on the arrray. The relevant patch (line numbers may not work out against 0.49) is below, would you be willing to try this? =================================================================== --- lib/Net/DNS/Resolver/Base.pm (revision 381) +++ lib/Net/DNS/Resolver/Base.pm (working copy) @@ -671,7 +671,7 @@ if ($ans->header->rcode ne "NOERROR" && $ans->header->rcode ne "NXDOMAIN"){ # Remove this one from the stack - print "RCODE: ".$ans->header->rcode ."; tying next nameserver\n" if $self->{'debug'}; + print "RCODE: ".$ans->header->rcode ."; trying next nameserver\n" if $self->{'debug'}; $lastanswer=$ans; next NAMESERVER ; @@ -853,6 +853,7 @@ # Try each nameserver. NAMESERVER: foreach my $ns (@ns) { + next if defined $ns->[3]; if ($stop_time) { my $now = time; if ($stop_time < $now) { @@ -886,7 +887,7 @@ unless ($sock[$nssockfamily]->send($packet_data, 0, $nsaddr)) { print ";; send error: $!\n" if $self->{'debug'}; $self->errorstring("Send error: $!"); - @ns = grep { $_->[0] ne $nsname } @ns; + $ns->[3]="Send error".$self->errorstring(); next; } @@ -919,8 +920,9 @@ if ($ans->header->rcode ne "NOERROR" && $ans->header->rcode ne "NXDOMAIN"){ # Remove this one from the stack - @ns = grep { $_->[0] ne $ready->peerhost } @ns; - print "RCODE: ".$ans->header->rcode ."; tying next nameserver\n" if $self->{'debug'}; + + print "RCODE: ".$ans->header->rcode ."; trying next nameserver\n" if $self->{'debug'}; + $ns->[3]="RCODE: ".$ans->header->rcode(); $lastanswer=$ans; next NAMESERVER ; @@ -939,8 +941,7 @@ $self->errorstring, "\n" if $self->{'debug'}; - @ns = grep { $_->[0] ne $ready->peerhost } @ns; - + $ns->[3]="Recv error ".$self->errorstring(); return unless @ns; } } #SELECTOR LOOP
[OLAF - Tue Jun 14 18:08:47 2005]: That previous patch will work but is not yet rocksolid. I've made some other patches to some of-trunk code that I would like to have tried. For one it fixes the backward compatibility for use bytes; If you could contact me at olaf@net-dns.org I can send you a tar ball. --Olaf