Subject: | Default LocalAddr broken in Net::DNS::Nameserver 0.62 |
Net::DNS::Nameserver is documented to listen on all local addresses if
no LocalAddr is set as a constructor option. This no longer works in
0.62; if no LocalAddr is passed, the ->main_loop method on
Net::DNS::Nameserver enters a tight loop, repeatedly trying to read from
an IO::Select object with no sockets.
The attached patch seems to be the simplest change to restore the
documented behaviour, and includes tests to verify that the created
select object has at least one socket. The new tests fail with 0.62 as
released, and pass with my patch to Net::DNS::Nameserver.
But there are two caveats for that patch. First, I haven't thought at
all about what's needed for IPv6. Second, I confess that the
constructor's behaviour as introduced in r688 is somewhat obscure to me.
What's the purpose of the Net::DNS::Resolver object here? And why is
->nameservers called twice on the resolver, once with @DEFAULT_ADDR, and
once with the @LocalAddr passed to the constructor?
(Also, I'm afraid Googling has failed me on this, but if there's a
mailing list or anything for Net::DNS, I'd be very interested in
subscribing.)
Subject: | net_dns_default_localaddr.diff |
Index: lib/Net/DNS/Nameserver.pm
===================================================================
--- lib/Net/DNS/Nameserver.pm (revision 701)
+++ lib/Net/DNS/Nameserver.pm (working copy)
@@ -63,7 +63,8 @@
}
# local server addresses must also be accepted by a resolver
- my @LocalAddr = ref $self{LocalAddr} ? @{$self{LocalAddr}} : ($self{LocalAddr});
+ my @LocalAddr = ref $self{LocalAddr} ? @{$self{LocalAddr}}
+ : ($self{LocalAddr} || '0.0.0.0');
my $resolver = Net::DNS::Resolver->new;
$resolver->nameservers(@DEFAULT_ADDR);
my @localaddresses = $resolver->nameservers(@LocalAddr);
Index: t/13-nameserver.t
===================================================================
--- t/13-nameserver.t (revision 0)
+++ t/13-nameserver.t (revision 0)
@@ -0,0 +1,22 @@
+# $Id$ -*- perl
+
+use Test::More tests => 10;
+use strict;
+
+use_ok('Net::DNS::Nameserver');
+
+for ([LocalAddr => '0.0.0.0'], [LocalAddr => '127.0.0.1'], []) {
+ my $nameserver = Net::DNS::Nameserver->new(
+ LocalPort => 8053,
+ ReplyHandler => sub { 'NXDOMAIN' },
+ @$_,
+ );
+ # This is a white-box test; it knows (too much?) about the implementation
+ ok($nameserver, "created server @$_");
+ my $select = $nameserver->{select};
+ ok($select, "got IO::Select for server @$_");
+ SKIP: {
+ skip 'skip check for handles if no IO::Select', 1 if !$select;
+ ok($select->count, "got sockets for server @$_");
+ }
+}