46
47
use IO::Socket::INET;
47
48
use Errno qw(EADDRINUSE EACCES);
49
use Time::HiRes qw(time);
49
51
use constant HAS_SOCKET_INET6 => eval { require IO::Socket::INET6; };
53
# Load Time::HiRes if it's available
55
eval { require Time::HiRes };
56
Time::HiRes->import( qw(time) ) unless $@;
59
55
###########################################################################
134
130
$self->{res}->persistent_udp(0); # bug 3997
137
}; # or warn "dns: eval failed: $@ $!\n";
134
my $eval_stat = $@ ne '' ? $@ : "errno=$!"; chomp $eval_stat;
135
dbg("dns: eval failed: $eval_stat");
139
138
dbg("dns: no ipv6") if $force_ipv4;
140
dbg("dns: is Net::DNS::Resolver available? " .
141
($self->{no_resolver} ? "no" : "yes"));
139
dbg("dns: is Net::DNS::Resolver available? %s",
140
$self->{no_resolver} ? "no" : "yes" );
142
141
if (!$self->{no_resolver} && defined $Net::DNS::VERSION) {
143
dbg("dns: Net::DNS version: ".$Net::DNS::VERSION);
142
dbg("dns: Net::DNS version: %s", $Net::DNS::VERSION);
146
145
return (!$self->{no_resolver});
203
204
$srcaddr = "0.0.0.0";
206
dbg("dns: name server: $ns, LocalAddr: $srcaddr");
207
dbg("dns: name server: %s, LocalAddr: %s", $ns,$srcaddr);
208
209
# find next available unprivileged port (1024 - 65535)
209
210
# starting at a random value to spread out use of ports
229
230
if (defined $sock) { # ok, got it
231
232
} elsif ($! == EADDRINUSE || $! == EACCES) { # in use, let's try another source port
232
dbg("dns: UDP port $lport already in use, trying another port");
233
dbg("dns: UDP port %s already in use, trying another port", $lport);
234
warn "Error creating a DNS resolver socket: $errno";
235
warn "error creating a DNS resolver socket: $errno";
238
239
if (!defined $sock) {
239
warn "Can't create a DNS resolver socket: $errno";
240
warn "cannot create a DNS resolver socket: $errno";
244
245
my($bufsiz,$newbufsiz);
245
246
$bufsiz = $sock->sockopt(Socket::SO_RCVBUF)
246
or die "Can't get a resolver socket rx buffer size: $!";
247
or die "cannot get a resolver socket rx buffer size: $!";
247
248
if ($bufsiz >= 32*1024) {
248
249
dbg("dns: resolver socket rx buffer size is %d bytes", $bufsiz);
250
251
$sock->sockopt(Socket::SO_RCVBUF, 32*1024)
251
or die "Can't set a resolver socket rx buffer size: $!";
252
or die "cannot set a resolver socket rx buffer size: $!";
252
253
$newbufsiz = $sock->sockopt(Socket::SO_RCVBUF)
253
or die "Can't get a resolver socket rx buffer size: $!";
254
or die "cannot get a resolver socket rx buffer size: $!";
254
255
dbg("dns: resolver socket rx buffer size changed from %d to %d bytes",
255
256
$bufsiz, $newbufsiz);
319
320
$packet = Net::DNS::Packet->new($host, $type, $class);
321
322
# a bit noisy, so commented by default...
322
#dbg("dns: new DNS packet time=".time()." host=$host type=$type id=".$packet->id);
323
#dbg("dns: new DNS packet time=%s host=%s type=%s id=%s",
324
# time, $host, $type, $packet->id);
325
327
my $eval_stat = $@ ne '' ? $@ : "errno=$!"; chomp $eval_stat;
334
336
# Internal function used only in this file
335
337
## compute an unique ID for a packet to match the query to the reply
336
338
## It must use only data that is returned unchanged by the nameserver.
337
## Argument is a Net::DNS::Packet that has a non-empty question section
338
## return is an object that can be used as a hash key
339
## Argument is a Net::DNS::Packet that has a non-empty question section,
340
## return is an (opaque) string that can be used as a hash key
340
342
my ($self, $packet) = @_;
341
343
my $header = $packet->header;
344
346
my $ques = $questions[0];
346
348
if (defined $ques) {
347
return join '/', $id, $ques->qname, $ques->qtype, $ques->qclass;
349
# Bug 6232: Net::DNS::Packet::new is not consistent in keeping data in
350
# sections of a packet either as original bytes or presentation-encoded:
351
# creating a query packet as above in new_dns_packet() keeps label in
352
# non-encoded form, yet on parsing an answer packet, its query section
353
# is converted to presentation form by Net::DNS::Question::parse calling
354
# Net::DNS::Packet::dn_expand and Net::DNS::wire2presentation in turn.
355
# Let's undo the effect of the wire2presentation routine here to make
356
# sure the query section of an answer packet matches the query section
357
# in our packet formed by new_dns_packet():
359
my $qname = $ques->qname;
360
$qname =~ s/\\([0-9]{3}|.)/length($1)==1 ? $1 : chr($1)/gse;
361
return join '/', $id, $qname, $ques->qtype, $ques->qclass;
349
364
# odd. this should not happen, but clearly some DNS servers
350
365
# can return something that Net::DNS interprets as having no
351
366
# question section. Better support it; just return the
352
367
# (safe) ID part, along with a text token indicating that
353
368
# the packet had no question part.
354
370
return $id . "NO_QUESTION_IN_PACKET";
414
431
return if $self->{no_resolver};
415
432
return if !$self->{sock};
417
my $waiting_time = 0;
419
435
my $rin = $self->{sock_as_vec};
423
my $now_before = time;
424
my ($nfound, $timeleft) = select($rout=$rin, undef, undef, $timeout);
439
my ($nfound, $timeleft);
440
{ my $timer; # collects timestamp when variable goes out of scope
441
if (!defined($timeout) || $timeout > 0)
442
{ $timer = $self->{main}->time_method("poll_dns_idle") }
443
($nfound, $timeleft) = select($rout=$rin, undef, undef, $timeout);
425
445
if (!defined $nfound || $nfound < 0) {
426
446
warn "dns: select failed: $!";
431
if ($now > $now_before && (!defined($timeout) || $timeout > 0)) {
432
$waiting_time += $now - $now_before;
434
451
$timeout = 0; # next time around collect whatever is available, then exit
435
452
last if $nfound == 0;