1package Net::DNS::Resolver::Base; 2# 3# $Id: Base.pm 704 2008-02-06 21:30:59Z olaf $ 4# 5 6use strict; 7 8BEGIN { 9 eval { require bytes; } 10} 11 12use vars qw( 13 $VERSION 14 $has_inet6 15 $AUTOLOAD 16); 17 18use Carp; 19use Config (); 20use Socket; 21use IO::Socket; 22use IO::Select; 23 24use Net::DNS; 25use Net::DNS::Packet; 26 27$VERSION = (qw$LastChangedRevision: 704 $)[1]; 28 29 30# 31# A few implementation notes wrt IPv6 support. 32# 33# In general we try to be gracious to those stacks that do not have ipv6 support. 34# We test that by means of the availability of Socket6 and IO::Socket::INET6 35# 36 37 38# We have chosen to not use mapped IPv4 addresses, there seem to be 39# issues with this; as a result we have to use sockets for both 40# family types. To be able to deal with persistent sockets and 41# sockets of both family types we use an array that is indexed by the 42# socketfamily type to store the socket handlers. I think this could 43# be done more efficiently. 44 45 46# inet_pton is not available on WIN32, so we only use the getaddrinfo 47# call to translate IP addresses to socketaddress 48 49 50 51# Set the $force_inet4_only variable inside the BEGIN block to force 52# not to use the IPv6 stuff. You can use this for compatibility 53# test. We do not see a need to do this from the calling code. 54 55 56# Olaf Kolkman, RIPE NCC, December 2003. 57 58 59BEGIN { 60 if ( 61 eval {require Socket6;} && 62 # INET6 prior to 2.01 will not work; sorry. 63 eval {require IO::Socket::INET6; IO::Socket::INET6->VERSION("2.00");} 64 ) { 65 import Socket6; 66 $has_inet6=1; 67 }else{ 68 $has_inet6=0; 69 } 70 } 71 72 73 74 75 76 77# 78# Set up a closure to be our class data. 79# 80{ 81 my %defaults = ( 82 nameservers => ['127.0.0.1'], 83 port => 53, 84 srcaddr => '0.0.0.0', 85 srcport => 0, 86 domain => '', 87 searchlist => [], 88 retrans => 5, 89 retry => 4, 90 usevc => 0, 91 stayopen => 0, 92 igntc => 0, 93 recurse => 1, 94 defnames => 1, 95 dnsrch => 1, 96 debug => 0, 97 errorstring => 'unknown error or no error', 98 tsig_rr => undef, 99 answerfrom => '', 100 querytime => undef, 101 tcp_timeout => 120, 102 udp_timeout => undef, 103 axfr_sel => undef, 104 axfr_rr => [], 105 axfr_soa_count => 0, 106 persistent_tcp => 0, 107 persistent_udp => 0, 108 dnssec => 0, 109 udppacketsize => 0, # The actual default is lower bound by Net::DNS::PACKETSZ 110 cdflag => 1, # this is only used when {dnssec} == 1 111 force_v4 => 0, # force_v4 is only relevant when we have 112 # v6 support available 113 ignqrid => 0, # normally packets with non-matching ID 114 # or with the qr bit of are thrown away 115 # in 'ignqrid' these packets are 116 # are accepted. 117 # USE WITH CARE, YOU ARE VULNARABLE TO 118 # SPOOFING IF SET. 119 # This is may be a temporary feature 120 ); 121 122 # If we're running under a SOCKSified Perl, use TCP instead of UDP 123 # and keep the sockets open. 124 if ($Config::Config{'usesocks'}) { 125 $defaults{'usevc'} = 1; 126 $defaults{'persistent_tcp'} = 1; 127 } 128 129 sub defaults { \%defaults } 130} 131 132# These are the attributes that we let the user specify in the new(). 133# We also deprecate access to these with AUTOLOAD (some may be useful). 134my %public_attr = map { $_ => 1 } qw( 135 nameservers 136 port 137 srcaddr 138 srcport 139 domain 140 searchlist 141 retrans 142 retry 143 usevc 144 stayopen 145 igntc 146 recurse 147 defnames 148 dnsrch 149 debug 150 tcp_timeout 151 udp_timeout 152 persistent_tcp 153 persistent_udp 154 dnssec 155 ignqrid 156); 157 158 159sub new { 160 my $class = shift; 161 my $self = bless({ %{$class->defaults} }, $class); 162 163 $self->_process_args(@_) if @_ and @_ % 2 == 0; 164 return $self; 165} 166 167 168 169sub _process_args { 170 my ($self, %args) = @_; 171 172 if ($args{'config_file'}) { 173 $self->read_config_file($args{'config_file'}); 174 } 175 176 foreach my $attr (keys %args) { 177 next unless $public_attr{$attr}; 178 179 if ($attr eq 'nameservers' || $attr eq 'searchlist') { 180 181 die "Net::DNS::Resolver->new(): $attr must be an arrayref\n" unless 182 defined($args{$attr}) && UNIVERSAL::isa($args{$attr}, 'ARRAY'); 183 184 } 185 186 if ($attr eq 'nameservers') { 187 $self->nameservers(@{$args{$attr}}); 188 } else { 189 $self->{$attr} = $args{$attr}; 190 } 191 } 192 193 194} 195 196 197 198 199 200# 201# Some people have reported that Net::DNS dies because AUTOLOAD picks up 202# calls to DESTROY. 203# 204sub DESTROY {} 205 206 207sub read_env { 208 my ($invocant) = @_; 209 my $config = ref $invocant ? $invocant : $invocant->defaults; 210 211 $config->{'nameservers'} = [ $ENV{'RES_NAMESERVERS'} =~ m/(\S+)/g ] 212 if exists $ENV{'RES_NAMESERVERS'}; 213 214 $config->{'searchlist'} = [ split(' ', $ENV{'RES_SEARCHLIST'}) ] 215 if exists $ENV{'RES_SEARCHLIST'}; 216 217 $config->{'domain'} = $ENV{'LOCALDOMAIN'} 218 if exists $ENV{'LOCALDOMAIN'}; 219 220 if (exists $ENV{'RES_OPTIONS'}) { 221 foreach ($ENV{'RES_OPTIONS'} =~ m/(\S+)/g) { 222 my ($name, $val) = split(m/:/); 223 $val = 1 unless defined $val; 224 $config->{$name} = $val if exists $config->{$name}; 225 } 226 } 227} 228 229# 230# $class->read_config_file($filename) or $self->read_config_file($file) 231# 232sub read_config_file { 233 my ($invocant, $file) = @_; 234 my $config = ref $invocant ? $invocant : $invocant->defaults; 235 236 237 my @ns; 238 my @searchlist; 239 240 local *FILE; 241 242 open(FILE, "< $file") or croak "Could not open $file: $!"; 243 local $/ = "\n"; 244 local $_; 245 246 while (<FILE>) { 247 s/\s*[;#].*//; 248 249 # Skip ahead unless there's non-whitespace characters 250 next unless m/\S/; 251 252 SWITCH: { 253 /^\s*domain\s+(\S+)/ && do { 254 $config->{'domain'} = $1; 255 last SWITCH; 256 }; 257 258 /^\s*search\s+(.*)/ && do { 259 push(@searchlist, split(' ', $1)); 260 last SWITCH; 261 }; 262 263 /^\s*nameserver\s+(.*)/ && do { 264 foreach my $ns (split(' ', $1)) { 265 $ns = '0.0.0.0' if $ns eq '0'; 266# next if $ns =~ m/:/; # skip IPv6 nameservers 267 push @ns, $ns; 268 } 269 last SWITCH; 270 }; 271 } 272 } 273 close FILE || croak "Could not close $file: $!"; 274 275 $config->{'nameservers'} = [ @ns ] if @ns; 276 $config->{'searchlist'} = [ @searchlist ] if @searchlist; 277 } 278 279 280 281 282sub print { print $_[0]->string } 283 284sub string { 285 my $self = shift; 286 287 my $timeout = defined $self->{'tcp_timeout'} ? $self->{'tcp_timeout'} : 'indefinite'; 288 my $hasINET6line= $has_inet6 ?" (IPv6 Transport is available)":" (IPv6 Transport is not available)"; 289 my $ignqrid=$self->{'ignqrid'} ? "\n;; ACCEPTING ALL PACKETS (IGNQRID)":""; 290 return <<END; 291;; RESOLVER state: 292;; domain = $self->{domain} 293;; searchlist = @{$self->{searchlist}} 294;; nameservers = @{$self->{nameservers}} 295;; port = $self->{port} 296;; srcport = $self->{srcport} 297;; srcaddr = $self->{srcaddr} 298;; tcp_timeout = $timeout 299;; retrans = $self->{retrans} retry = $self->{retry} 300;; usevc = $self->{usevc} stayopen = $self->{stayopen} igntc = $self->{igntc} 301;; defnames = $self->{defnames} dnsrch = $self->{dnsrch} 302;; recurse = $self->{recurse} debug = $self->{debug} 303;; force_v4 = $self->{force_v4} $hasINET6line $ignqrid 304END 305 306} 307 308 309sub searchlist { 310 my $self = shift; 311 $self->{'searchlist'} = [ @_ ] if @_; 312 return @{$self->{'searchlist'}}; 313} 314 315sub nameservers { 316 my $self = shift; 317 318 if (@_) { 319 my @a; 320 foreach my $ns (@_) { 321 next unless defined($ns); 322 if ( _ip_is_ipv4($ns) ) { 323 push @a, ($ns eq '0') ? '0.0.0.0' : $ns; 324 325 } elsif ( _ip_is_ipv6($ns) ) { 326 push @a, ($ns eq '0') ? '::0' : $ns; 327 328 } else { 329 my $defres = Net::DNS::Resolver->new; 330 my @names; 331 332 if ($ns !~ /\./) { 333 if (defined $defres->searchlist) { 334 @names = map { $ns . '.' . $_ } 335 $defres->searchlist; 336 } elsif (defined $defres->domain) { 337 @names = ($ns . '.' . $defres->domain); 338 } 339 } 340 else { 341 @names = ($ns); 342 } 343 344 my $packet = $defres->search($ns); 345 $self->errorstring($defres->errorstring); 346 if (defined($packet)) { 347 push @a, cname_addr([@names], $packet); 348 } 349 } 350 } 351 352 353 $self->{'nameservers'} = [ @a ]; 354 } 355 my @returnval; 356 foreach my $ns (@{$self->{'nameservers'}}){ 357 next if _ip_is_ipv6($ns) && (! $has_inet6 || $self->force_v4() ); 358 push @returnval, $ns; 359 } 360 361 return @returnval; 362} 363 364sub nameserver { &nameservers } 365 366sub cname_addr { 367 my $names = shift; 368 my $packet = shift; 369 my @addr; 370 my @names = @{$names}; 371 372 my $oct2 = '(?:2[0-4]\d|25[0-5]|[0-1]?\d\d|\d)'; 373 374 RR: foreach my $rr ($packet->answer) { 375 next RR unless grep {$rr->name} @names; 376 377 if ($rr->type eq 'CNAME') { 378 push(@names, $rr->cname); 379 } elsif ($rr->type eq 'A') { 380 # Run a basic taint check. 381 next RR unless $rr->address =~ m/^($oct2\.$oct2\.$oct2\.$oct2)$/o; 382 383 push(@addr, $1) 384 } 385 } 386 387 388 return @addr; 389} 390 391 392# if ($self->{"udppacketsize"} > Net::DNS::PACKETSZ() 393# then we use EDNS and $self->{"udppacketsize"} 394# should be taken as the maximum packet_data length 395sub _packetsz { 396 my ($self) = @_; 397 398 return $self->{"udppacketsize"} > Net::DNS::PACKETSZ() ? 399 $self->{"udppacketsize"} : Net::DNS::PACKETSZ(); 400} 401 402sub _reset_errorstring { 403 my ($self) = @_; 404 405 $self->errorstring($self->defaults->{'errorstring'}); 406} 407 408 409sub search { 410 my $self = shift; 411 my $name = shift || '.'; 412 413 my $defdomain = $self->{domain} if $self->{defnames}; 414 my @searchlist = @{$self->{searchlist}} if $self->{dnsrch}; 415 416 # resolve name by trying as absolute name, then applying searchlist 417 my @list = (undef, @searchlist); 418 for ($name) { 419 # resolve name with no dots or colons by applying searchlist (or domain) 420 @list = @searchlist ? @searchlist : ($defdomain) unless m/[:.]/; 421 # resolve name with trailing dot as absolute name 422 @list = (undef) if m/\.$/; 423 } 424 425 foreach my $suffix ( @list ) { 426 my $fqname = join '.', $name, ($suffix || ()); 427 428 print ';; search(', join(', ', $fqname, @_), ")\n" if $self->{debug}; 429 430 my $packet = $self->send($fqname, @_) || return undef; 431 432 next unless ($packet->header->rcode eq "NOERROR"); # something 433 #useful happened 434 return $packet if $packet->header->ancount; # answer found 435 next unless $packet->header->qdcount; # question empty? 436 437 last if ($packet->question)[0]->qtype eq 'PTR'; # abort search if IP 438 } 439 return undef; 440} 441 442 443sub query { 444 my $self = shift; 445 my $name = shift || '.'; 446 447 # resolve name containing no dots or colons by appending domain 448 my @suffix = ($self->{domain} || ()) if $name !~ m/[:.]/ and $self->{defnames}; 449 450 my $fqname = join '.', $name, @suffix; 451 452 print ';; query(', join(', ', $fqname, @_), ")\n" if $self->{debug}; 453 454 my $packet = $self->send($fqname, @_) || return undef; 455 456 return $packet if $packet->header->ancount; # answer found 457 return undef; 458} 459 460 461sub send { 462 my $self = shift; 463 my $packet = $self->make_query_packet(@_); 464 my $packet_data = $packet->data; 465 466 467 my $ans; 468 469 if ($self->{'usevc'} || length $packet_data > $self->_packetsz) { 470 471 $ans = $self->send_tcp($packet, $packet_data); 472 473 } else { 474 $ans = $self->send_udp($packet, $packet_data); 475 476 if ($ans && $ans->header->tc && !$self->{'igntc'}) { 477 print ";;\n;; packet truncated: retrying using TCP\n" if $self->{'debug'}; 478 $ans = $self->send_tcp($packet, $packet_data); 479 } 480 } 481 482 return $ans; 483} 484 485 486 487sub send_tcp { 488 my ($self, $packet, $packet_data) = @_; 489 my $lastanswer; 490 491 my $srcport = $self->{'srcport'}; 492 my $srcaddr = $self->{'srcaddr'}; 493 my $dstport = $self->{'port'}; 494 495 unless ( $self->nameservers()) { 496 $self->errorstring('no nameservers'); 497 print ";; ERROR: send_tcp: no nameservers\n" if $self->{'debug'}; 498 return; 499 } 500 501 $self->_reset_errorstring; 502 503 504 NAMESERVER: foreach my $ns ($self->nameservers()) { 505 506 print ";; attempt to send_tcp($ns:$dstport) (src port = $srcport)\n" 507 if $self->{'debug'}; 508 509 510 511 my $sock; 512 my $sock_key = "$ns:$dstport"; 513 my ($host,$port); 514 if ($self->persistent_tcp && $self->{'sockets'}[AF_UNSPEC]{$sock_key}) { 515 $sock = $self->{'sockets'}[AF_UNSPEC]{$sock_key}; 516 print ";; using persistent socket\n" 517 if $self->{'debug'}; 518 unless ($sock->connected){ 519 print ";; persistent socket disconnected (trying to reconnect)" 520 if $self->{'debug'}; 521 undef($sock); 522 $sock= $self->_create_tcp_socket($ns); 523 next NAMESERVER unless $sock; 524 $self->{'sockets'}[AF_UNSPEC]{$sock_key} = $sock; 525 } 526 527 } else { 528 $sock= $self->_create_tcp_socket($ns); 529 next NAMESERVER unless $sock; 530 531 $self->{'sockets'}[AF_UNSPEC]{$sock_key} = $sock if 532 $self->persistent_tcp; 533 } 534 535 536 my $lenmsg = pack('n', length($packet_data)); 537 print ';; sending ', length($packet_data), " bytes\n" 538 if $self->{'debug'}; 539 540 # note that we send the length and packet data in a single call 541 # as this produces a single TCP packet rather than two. This 542 # is more efficient and also makes things much nicer for sniffers. 543 # (ethereal doesn't seem to reassemble DNS over TCP correctly) 544 545 546 unless ($sock->send( $lenmsg . $packet_data)) { 547 $self->errorstring($!); 548 print ";; ERROR: send_tcp: data send failed: $!\n" 549 if $self->{'debug'}; 550 next NAMESERVER; 551 } 552 553 my $sel = IO::Select->new($sock); 554 my $timeout=$self->{'tcp_timeout'}; 555 if ($sel->can_read($timeout)) { 556 my $buf = read_tcp($sock, Net::DNS::INT16SZ(), $self->{'debug'}); 557 next NAMESERVER unless length($buf); # Failure to get anything 558 my ($len) = unpack('n', $buf); 559 next NAMESERVER unless $len; # Cannot determine size 560 561 unless ($sel->can_read($timeout)) { 562 $self->errorstring('timeout'); 563 print ";; TIMEOUT\n" if $self->{'debug'}; 564 next; 565 } 566 567 $buf = read_tcp($sock, $len, $self->{'debug'}); 568 569 $self->answerfrom($sock->peerhost); 570 571 print ';; received ', length($buf), " bytes\n" 572 if $self->{'debug'}; 573 574 unless (length($buf) == $len) { 575 $self->errorstring("expected $len bytes, " . 576 'received ' . length($buf)); 577 next; 578 } 579 580 my ($ans, $err) = Net::DNS::Packet->new(\$buf, $self->{'debug'}); 581 if (defined $ans) { 582 $self->errorstring($ans->header->rcode); 583 $ans->answerfrom($self->answerfrom); 584 585 if ($ans->header->rcode ne "NOERROR" && 586 $ans->header->rcode ne "NXDOMAIN"){ 587 # Remove this one from the stack 588 print "RCODE: ".$ans->header->rcode ."; trying next nameserver\n" if $self->{'debug'}; 589 $lastanswer=$ans; 590 next NAMESERVER ; 591 592 } 593 594 } 595 elsif (defined $err) { 596 $self->errorstring($err); 597 } 598 599 return $ans; 600 } 601 else { 602 $self->errorstring('timeout'); 603 next; 604 } 605 } 606 607 if ($lastanswer){ 608 $self->errorstring($lastanswer->header->rcode ); 609 return $lastanswer; 610 611 } 612 613 return; 614} 615 616 617 618sub send_udp { 619 my ($self, $packet, $packet_data) = @_; 620 my $retrans = $self->{'retrans'}; 621 my $timeout = $retrans; 622 623 my $lastanswer; 624 625 my $stop_time = time + $self->{'udp_timeout'} if $self->{'udp_timeout'}; 626 627 $self->_reset_errorstring; 628 629 my @ns; 630 my $dstport = $self->{'port'}; 631 my $srcport = $self->{'srcport'}; 632 my $srcaddr = $self->{'srcaddr'}; 633 634 my @sock; 635 636 637 if ($self->persistent_udp){ 638 if ($has_inet6){ 639 if ( defined ($self->{'sockets'}[AF_INET6()]{'UDP'})) { 640 $sock[AF_INET6()] = $self->{'sockets'}[AF_INET6()]{'UDP'}; 641 print ";; using persistent AF_INET6() family type socket\n" 642 if $self->{'debug'}; 643 } 644 } 645 if ( defined ($self->{'sockets'}[AF_INET]{'UDP'})) { 646 $sock[AF_INET] = $self->{'sockets'}[AF_INET]{'UDP'}; 647 print ";; using persistent AF_INET() family type socket\n" 648 if $self->{'debug'}; 649 } 650 } 651 652 if ($has_inet6 && ! $self->force_v4() && !defined( $sock[AF_INET6()] )){ 653 654 655 # '::' Otherwise the INET6 socket will fail. 656 657 my $srcaddr6 = $srcaddr eq '0.0.0.0' ? '::' : $srcaddr; 658 659 print ";; Trying to set up a AF_INET6() family type UDP socket with srcaddr: $srcaddr ... " 660 if $self->{'debug'}; 661 662 663 # IO::Socket carps on errors if Perl's -w flag is turned on. 664 # Uncomment the next two lines and the line following the "new" 665 # call to turn off these messages. 666 667 #my $old_wflag = $^W; 668 #$^W = 0; 669 670 $sock[AF_INET6()] = IO::Socket::INET6->new( 671 LocalAddr => $srcaddr6, 672 LocalPort => ($srcport || undef), 673 Proto => 'udp', 674 ); 675 676 677 678 679 print (defined($sock[AF_INET6()])?"done\n":"failed\n") if $has_inet6 && $self->debug(); 680 681 } 682 683 # Always set up an AF_INET socket. 684 # It will be used if the address familly of for the endpoint is V4. 685 686 if (!defined( $sock[AF_INET])) 687 688 { 689 print ";; setting up an AF_INET() family type UDP socket\n" 690 if $self->{'debug'}; 691 692 #my $old_wflag = $^W; 693 #$^W = 0; 694 695 $sock[AF_INET] = IO::Socket::INET->new( 696 LocalAddr => $srcaddr, 697 LocalPort => ($srcport || undef), 698 Proto => 'udp', 699 ) ; 700 701 #$^W = $old_wflag; 702 } 703 704 705 706 unless (defined $sock[AF_INET] || ($has_inet6 && defined $sock[AF_INET6()])) { 707 708 $self->errorstring("could not get socket"); #' 709 return; 710 } 711 712 $self->{'sockets'}[AF_INET]{'UDP'} = $sock[AF_INET] if ($self->persistent_udp) && defined( $sock[AF_INET] ); 713 $self->{'sockets'}[AF_INET6()]{'UDP'} = $sock[AF_INET6()] if $has_inet6 && ($self->persistent_udp) && defined( $sock[AF_INET6()]) && ! $self->force_v4(); 714 715 # Constructing an array of arrays that contain 3 elements: The 716 # nameserver IP address, its sockaddr and the sockfamily for 717 # which the sockaddr structure is constructed. 718 719 my $nmbrnsfailed=0; 720 NSADDRESS: foreach my $ns_address ($self->nameservers()){ 721 # The logic below determines the $dst_sockaddr. 722 # If getaddrinfo is available that is used for both INET4 and INET6 723 # If getaddrinfo is not avialable (Socket6 failed to load) we revert 724 # to the 'classic mechanism 725 if ($has_inet6 && ! $self->force_v4() ){ 726 # we can use getaddrinfo 727 no strict 'subs'; # Because of the eval statement in the BEGIN 728 # AI_NUMERICHOST is not available at compile time. 729 # The AI_NUMERICHOST surpresses lookups. 730 731 my $old_wflag = $^W; #circumvent perl -w warnings about 'udp' 732 $^W = 0; 733 734 735 736 my @res = getaddrinfo($ns_address, $dstport, AF_UNSPEC, SOCK_DGRAM, 737 0, AI_NUMERICHOST); 738 739 $^W=$old_wflag ; 740 741 742 use strict 'subs'; 743 744 my ($sockfamily, $socktype_tmp, 745 $proto_tmp, $dst_sockaddr, $canonname_tmp) = @res; 746 747 if (scalar(@res) < 5) { 748 die ("can't resolve \"$ns_address\" to address"); 749 } 750 751 push @ns,[$ns_address,$dst_sockaddr,$sockfamily]; 752 753 }else{ 754 next NSADDRESS unless( _ip_is_ipv4($ns_address)); 755 my $dst_sockaddr = sockaddr_in($dstport, inet_aton($ns_address)); 756 push @ns, [$ns_address,$dst_sockaddr,AF_INET]; 757 } 758 759 } 760 761 unless (@ns) { 762 print "No nameservers" if $self->debug(); 763 $self->errorstring('no nameservers'); 764 return; 765 } 766 767 my $sel = IO::Select->new() ; 768 # We allready tested that one of the two socket exists 769 770 $sel->add($sock[AF_INET]) if defined ($sock[AF_INET]); 771 $sel->add($sock[AF_INET6()]) if $has_inet6 && defined ($sock[AF_INET6()]) && ! $self->force_v4(); 772 773 774 # Perform each round of retries. 775 for (my $i = 0; 776 $i < $self->{'retry'}; 777 ++$i, $retrans *= 2, $timeout = int($retrans / (@ns || 1))) { 778 779 $timeout = 1 if ($timeout < 1); 780 781 # Try each nameserver. 782 NAMESERVER: foreach my $ns (@ns) { 783 next if defined $ns->[3]; 784 if ($stop_time) { 785 my $now = time; 786 if ($stop_time < $now) { 787 $self->errorstring('query timed out'); 788 return; 789 } 790 if ($timeout > 1 && $timeout > ($stop_time-$now)) { 791 $timeout = $stop_time-$now; 792 } 793 } 794 my $nsname = $ns->[0]; 795 my $nsaddr = $ns->[1]; 796 my $nssockfamily = $ns->[2]; 797 798 # If we do not have a socket for the transport 799 # we are supposed to reach the namserver on we 800 # should skip it. 801 unless (defined ($sock[ $nssockfamily ])){ 802 print "Send error: cannot reach $nsname (". 803 804 ( ($has_inet6 && $nssockfamily == AF_INET6()) ? "IPv6" : "" ). 805 ( ($nssockfamily == AF_INET) ? "IPv4" : "" ). 806 ") not available" 807 if $self->debug(); 808 809 810 $self->errorstring("Send error: cannot reach $nsname (" . 811 ( ($has_inet6 && $nssockfamily == AF_INET6()) ? "IPv6" : "" ). 812 ( ($nssockfamily == AF_INET) ? "IPv4" : "" ). 813 ") not available" 814 815); 816 next NAMESERVER ; 817 } 818 819 print ";; send_udp($nsname:$dstport)\n" 820 if $self->{'debug'}; 821 822 unless ($sock[$nssockfamily]->send($packet_data, 0, $nsaddr)) { 823 print ";; send error: $!\n" if $self->{'debug'}; 824 $self->errorstring("Send error: $!"); 825 $nmbrnsfailed++; 826 $ns->[3]="Send error".$self->errorstring(); 827 next; 828 } 829 830 # See ticket 11931 but this works not quite yet 831 my $oldpacket_timeout=time+$timeout; 832 until ( $oldpacket_timeout && ($oldpacket_timeout < time())) { 833 my @ready = $sel->can_read($timeout); 834 SELECTOR: foreach my $ready (@ready) { 835 my $buf = ''; 836 837 if ($ready->recv($buf, $self->_packetsz)) { 838 839 $self->answerfrom($ready->peerhost); 840 841 print ';; answer from ', 842 $ready->peerhost, ':', 843 $ready->peerport, ' : ', 844 length($buf), " bytes\n" 845 if $self->{'debug'}; 846 847 my ($ans, $err) = Net::DNS::Packet->new(\$buf, $self->{'debug'}); 848 849 if (defined $ans) { 850 next SELECTOR unless ( $ans->header->qr || $self->{'ignqrid'}); 851 next SELECTOR unless ( ($ans->header->id == $packet->header->id) || $self->{'ignqrid'} ); 852 $self->errorstring($ans->header->rcode); 853 $ans->answerfrom($self->answerfrom); 854 if ($ans->header->rcode ne "NOERROR" && 855 $ans->header->rcode ne "NXDOMAIN"){ 856 # Remove this one from the stack 857 858 print "RCODE: ".$ans->header->rcode ."; trying next nameserver\n" if $self->{'debug'}; 859 $nmbrnsfailed++; 860 $ns->[3]="RCODE: ".$ans->header->rcode(); 861 $lastanswer=$ans; 862 next NAMESERVER ; 863 864 } 865 } elsif (defined $err) { 866 $self->errorstring($err); 867 } 868 return $ans; 869 } else { 870 $self->errorstring($!); 871 print ';; recv ERROR(', 872 $ready->peerhost, ':', 873 $ready->peerport, '): ', 874 $self->errorstring, "\n" 875 if $self->{'debug'}; 876 $ns->[3]="Recv error ".$self->errorstring(); 877 $nmbrnsfailed++; 878 # We want to remain in the SELECTOR LOOP... 879 # unless there are no more nameservers 880 return unless ($nmbrnsfailed < @ns); 881 print ';; Number of failed nameservers: $nmbrnsfailed out of '.scalar @ns."\n" if $self->{'debug'}; 882 883 } 884 } #SELECTOR LOOP 885 } # until stop_time loop 886 } #NAMESERVER LOOP 887 888 } 889 890 if ($lastanswer){ 891 $self->errorstring($lastanswer->header->rcode ); 892 return $lastanswer; 893 894 } 895 if ($sel->handles) { 896 # If there are valid hanndles than we have either a timeout or 897 # a send error. 898 $self->errorstring('query timed out') unless ($self->errorstring =~ /Send error:/); 899 } 900 else { 901 if ($nmbrnsfailed < @ns){ 902 $self->errorstring('Unexpected Error') ; 903 }else{ 904 $self->errorstring('all nameservers failed'); 905 } 906 } 907 return; 908} 909 910 911sub bgsend { 912 my $self = shift; 913 914 unless ($self->nameservers()) { 915 $self->errorstring('no nameservers'); 916 return; 917 } 918 919 $self->_reset_errorstring; 920 921 my $packet = $self->make_query_packet(@_); 922 my $packet_data = $packet->data; 923 924 my $srcaddr = $self->{'srcaddr'}; 925 my $srcport = $self->{'srcport'}; 926 927 928 my (@res, $sockfamily, $dst_sockaddr); 929 my $ns_address = ($self->nameservers())[0]; 930 my $dstport = $self->{'port'}; 931 932 933 # The logic below determines ther $dst_sockaddr. 934 # If getaddrinfo is available that is used for both INET4 and INET6 935 # If getaddrinfo is not avialable (Socket6 failed to load) we revert 936 # to the 'classic mechanism 937 if ($has_inet6 && ! $self->force_v4()){ 938 939 my ( $socktype_tmp, $proto_tmp, $canonname_tmp); 940 941 no strict 'subs'; # Because of the eval statement in the BEGIN 942 # AI_NUMERICHOST is not available at compile time. 943 944 # The AI_NUMERICHOST surpresses lookups. 945 my @res = getaddrinfo($ns_address, $dstport, AF_UNSPEC, SOCK_DGRAM, 946 0 , AI_NUMERICHOST); 947 948 use strict 'subs'; 949 950 ($sockfamily, $socktype_tmp, 951 $proto_tmp, $dst_sockaddr, $canonname_tmp) = @res; 952 953 if (scalar(@res) < 5) { 954 die ("can't resolve \"$ns_address\" to address (it could have been an IP address)"); 955 } 956 957 }else{ 958 $sockfamily=AF_INET; 959 960 if (! _ip_is_ipv4($ns_address)){ 961 $self->errorstring("bgsend(ipv4 only):$ns_address does not seem to be a valid IPv4 address"); 962 return; 963 } 964 965 $dst_sockaddr = sockaddr_in($dstport, inet_aton($ns_address)); 966 } 967 my @socket; 968 969 if ($sockfamily == AF_INET) { 970 $socket[$sockfamily] = IO::Socket::INET->new( 971 Proto => 'udp', 972 Type => SOCK_DGRAM, 973 LocalAddr => $srcaddr, 974 LocalPort => ($srcport || undef), 975 ); 976 } elsif ($has_inet6 && $sockfamily == AF_INET6() ) { 977 # Otherwise the INET6 socket will just fail 978 my $srcaddr6 = $srcaddr eq "0.0.0.0" ? '::' : $srcaddr; 979 $socket[$sockfamily] = IO::Socket::INET6->new( 980 Proto => 'udp', 981 Type => SOCK_DGRAM, 982 LocalAddr => $srcaddr6, 983 LocalPort => ($srcport || undef), 984 ); 985 } else { 986 die ref($self)." bgsend:Unsoported Socket Family: $sockfamily"; 987 } 988 989 unless (scalar(@socket)) { 990 $self->errorstring("could not get socket"); #' 991 return; 992 } 993 994 print ";; bgsend($ns_address : $dstport)\n" if $self->{'debug'} ; 995 996 foreach my $socket (@socket){ 997 next if !defined $socket; 998 999 unless ($socket->send($packet_data,0,$dst_sockaddr)){ 1000 my $err = $!; 1001 print ";; send ERROR($ns_address): $err\n" if $self->{'debug'}; 1002 1003 $self->errorstring("Send: ".$err); 1004 return; 1005 } 1006 return $socket; 1007 } 1008 $self->errorstring("Could not find a socket to send on"); 1009 return; 1010 1011} 1012 1013sub bgread { 1014 my ($self, $sock) = @_; 1015 1016 my $buf = ''; 1017 1018 my $peeraddr = $sock->recv($buf, $self->_packetsz); 1019 1020 if ($peeraddr) { 1021 print ';; answer from ', $sock->peerhost, ':', 1022 $sock->peerport, ' : ', length($buf), " bytes\n" 1023 if $self->{'debug'}; 1024 1025 my ($ans, $err) = Net::DNS::Packet->new(\$buf, $self->{'debug'}); 1026 1027 if (defined $ans) { 1028 $self->errorstring($ans->header->rcode); 1029 $ans->answerfrom($sock->peerhost); 1030 } elsif (defined $err) { 1031 $self->errorstring($err); 1032 } 1033 1034 return $ans; 1035 } else { 1036 $self->errorstring($!); 1037 return; 1038 } 1039} 1040 1041sub bgisready { 1042 my $self = shift; 1043 my $sel = IO::Select->new(@_); 1044 my @ready = $sel->can_read(0.0); 1045 return @ready > 0; 1046} 1047 1048sub make_query_packet { 1049 my $self = shift; 1050 my $packet; 1051 1052 if (ref($_[0]) and $_[0]->isa('Net::DNS::Packet')) { 1053 $packet = shift; 1054 } else { 1055 $packet = Net::DNS::Packet->new(@_); 1056 } 1057 1058 if ($packet->header->opcode eq 'QUERY') { 1059 $packet->header->rd($self->{'recurse'}); 1060 } 1061 1062 if ($self->{'dnssec'}) { 1063 # RFC 3225 1064 print ";; Adding EDNS extention with UDP packetsize $self->{'udppacketsize'} and DNS OK bit set\n" 1065 if $self->{'debug'}; 1066 1067 my $optrr = Net::DNS::RR->new( 1068 Type => 'OPT', 1069 Name => '', 1070 Class => $self->{'udppacketsize'}, # Decimal UDPpayload 1071 ednsflags => 0x8000, # first bit set see RFC 3225 1072 ); 1073 1074 1075 $packet->push('additional', $optrr) unless defined $packet->{'optadded'} ; 1076 $packet->{'optadded'}=1; 1077 } elsif ($self->{'udppacketsize'} > Net::DNS::PACKETSZ()) { 1078 print ";; Adding EDNS extention with UDP packetsize $self->{'udppacketsize'}.\n" if $self->{'debug'}; 1079 # RFC 3225 1080 my $optrr = Net::DNS::RR->new( 1081 Type => 'OPT', 1082 Name => '', 1083 Class => $self->{'udppacketsize'}, # Decimal UDPpayload 1084 TTL => 0x0000 # RCODE 32bit Hex 1085 ); 1086 1087 $packet->push('additional', $optrr) unless defined $packet->{'optadded'} ; 1088 $packet->{'optadded'}=1; 1089 } 1090 1091 1092 if ($self->{'tsig_rr'}) { 1093 if (!grep { $_->type eq 'TSIG' } $packet->additional) { 1094 $packet->push('additional', $self->{'tsig_rr'}); 1095 } 1096 } 1097 1098 return $packet; 1099} 1100 1101sub axfr { 1102 my $self = shift; 1103 my @zone; 1104 1105 if ($self->axfr_start(@_)) { 1106 my ($rr, $err); 1107 while (($rr, $err) = $self->axfr_next, $rr && !$err) { 1108 push @zone, $rr; 1109 } 1110 @zone = () if $err; 1111 } 1112 1113 return @zone; 1114} 1115 1116sub axfr_old { 1117 croak "Use of Net::DNS::Resolver::axfr_old() is deprecated, use axfr() or axfr_start()."; 1118} 1119 1120 1121sub axfr_start { 1122 my $self = shift; 1123 my ($dname, $class) = @_; 1124 $dname ||= $self->{'searchlist'}->[0]; 1125 $class ||= 'IN'; 1126 my $timeout = $self->{'tcp_timeout'}; 1127 1128 unless ($dname) { 1129 print ";; ERROR: axfr: no zone specified\n" if $self->{'debug'}; 1130 $self->errorstring('no zone'); 1131 return; 1132 } 1133 1134 1135 print ";; axfr_start($dname, $class)\n" if $self->{'debug'}; 1136 1137 unless ($self->nameservers()) { 1138 $self->errorstring('no nameservers'); 1139 print ";; ERROR: no nameservers\n" if $self->{'debug'}; 1140 return; 1141 } 1142 1143 my $packet = $self->make_query_packet($dname, 'AXFR', $class); 1144 my $packet_data = $packet->data; 1145 1146 my $ns = ($self->nameservers())[0]; 1147 1148 1149 my $srcport = $self->{'srcport'}; 1150 my $srcaddr = $self->{'srcaddr'}; 1151 my $dstport = $self->{'port'}; 1152 1153 print ";; axfr_start nameserver = $ns\n" if $self->{'debug'}; 1154 print ";; axfr_start srcport: $srcport, srcaddr: $srcaddr, dstport: $dstport\n" if $self->{'debug'}; 1155 1156 1157 my $sock; 1158 my $sock_key = "$ns:$self->{'port'}"; 1159 1160 1161 if ($self->persistent_tcp && $self->{'axfr_sockets'}[AF_UNSPEC]{$sock_key}) { 1162 $sock = $self->{'axfr_sockets'}[AF_UNSPEC]{$sock_key}; 1163 print ";; using persistent socket\n" 1164 if $self->{'debug'}; 1165 } else { 1166 $sock=$self->_create_tcp_socket($ns); 1167 1168 return unless ($sock); # all error messages 1169 # are set by _create_tcp_socket 1170 1171 1172 $self->{'axfr_sockets'}[AF_UNSPEC]{$sock_key} = $sock if 1173 $self->persistent_tcp; 1174 } 1175 1176 my $lenmsg = pack('n', length($packet_data)); 1177 1178 unless ($sock->send($lenmsg)) { 1179 $self->errorstring($!); 1180 return; 1181 } 1182 1183 unless ($sock->send($packet_data)) { 1184 $self->errorstring($!); 1185 return; 1186 } 1187 1188 my $sel = IO::Select->new($sock); 1189 1190 $self->{'axfr_sel'} = $sel; 1191 $self->{'axfr_rr'} = []; 1192 $self->{'axfr_soa_count'} = 0; 1193 1194 return $sock; 1195} 1196 1197 1198sub axfr_next { 1199 my $self = shift; 1200 my $err = ''; 1201 1202 unless (@{$self->{'axfr_rr'}}) { 1203 unless ($self->{'axfr_sel'}) { 1204 my $err = 'no zone transfer in progress'; 1205 1206 print ";; $err\n" if $self->{'debug'}; 1207 $self->errorstring($err); 1208 1209 return wantarray ? (undef, $err) : undef; 1210 } 1211 1212 my $sel = $self->{'axfr_sel'}; 1213 my $timeout = $self->{'tcp_timeout'}; 1214 1215 #-------------------------------------------------------------- 1216 # Read the length of the response packet. 1217 #-------------------------------------------------------------- 1218 1219 my @ready = $sel->can_read($timeout); 1220 unless (@ready) { 1221 $err = 'timeout'; 1222 $self->errorstring($err); 1223 return wantarray ? (undef, $err) : undef; 1224 } 1225 1226 my $buf = read_tcp($ready[0], Net::DNS::INT16SZ(), $self->{'debug'}); 1227 unless (length $buf) { 1228 $err = 'truncated zone transfer'; 1229 $self->errorstring($err); 1230 return wantarray ? (undef, $err) : undef; 1231 } 1232 1233 my ($len) = unpack('n', $buf); 1234 unless ($len) { 1235 $err = 'truncated zone transfer'; 1236 $self->errorstring($err); 1237 return wantarray ? (undef, $err) : undef; 1238 } 1239 1240 #-------------------------------------------------------------- 1241 # Read the response packet. 1242 #-------------------------------------------------------------- 1243 1244 @ready = $sel->can_read($timeout); 1245 unless (@ready) { 1246 $err = 'timeout'; 1247 $self->errorstring($err); 1248 return wantarray ? (undef, $err) : undef; 1249 } 1250 1251 $buf = read_tcp($ready[0], $len, $self->{'debug'}); 1252 1253 print ';; received ', length($buf), " bytes\n" 1254 if $self->{'debug'}; 1255 1256 unless (length($buf) == $len) { 1257 $err = "expected $len bytes, received " . length($buf); 1258 $self->errorstring($err); 1259 print ";; $err\n" if $self->{'debug'}; 1260 return wantarray ? (undef, $err) : undef; 1261 } 1262 1263 my $ans; 1264 ($ans, $err) = Net::DNS::Packet->new(\$buf, $self->{'debug'}); 1265 1266 if ($ans) { 1267 if ($ans->header->rcode ne 'NOERROR') { 1268 $self->errorstring('Response code from server: ' . $ans->header->rcode); 1269 print ';; Response code from server: ' . $ans->header->rcode . "\n" if $self->{'debug'}; 1270 return wantarray ? (undef, $err) : undef; 1271 } 1272 if ($ans->header->ancount < 1) { 1273 $err = 'truncated zone transfer'; 1274 $self->errorstring($err); 1275 print ";; $err\n" if $self->{'debug'}; 1276 return wantarray ? (undef, $err) : undef; 1277 } 1278 } 1279 else { 1280 $err ||= 'unknown error during packet parsing'; 1281 $self->errorstring($err); 1282 print ";; $err\n" if $self->{'debug'}; 1283 return wantarray ? (undef, $err) : undef; 1284 } 1285 1286 foreach my $rr ($ans->answer) { 1287 if ($rr->type eq 'SOA') { 1288 if (++$self->{'axfr_soa_count'} < 2) { 1289 push @{$self->{'axfr_rr'}}, $rr; 1290 } 1291 } 1292 else { 1293 push @{$self->{'axfr_rr'}}, $rr; 1294 } 1295 } 1296 1297 if ($self->{'axfr_soa_count'} >= 2) { 1298 $self->{'axfr_sel'} = undef; 1299 # we need to mark the transfer as over if the responce was in 1300 # many answers. Otherwise, the user will call axfr_next again 1301 # and that will cause a 'no transfer in progress' error. 1302 push(@{$self->{'axfr_rr'}}, undef); 1303 } 1304 } 1305 1306 my $rr = shift @{$self->{'axfr_rr'}}; 1307 1308 return wantarray ? ($rr, undef) : $rr; 1309} 1310 1311 1312 1313 1314sub dnssec { 1315 my ($self, $new_val) = @_; 1316 if (defined $new_val) { 1317 $self->{"dnssec"} = $new_val; 1318 # Setting the udppacket size to some higher default 1319 $self->udppacketsize(2048) if $new_val; 1320 } 1321 1322 Carp::carp ("You called the Net::DNS::Resolver::dnssec() method but do not have Net::DNS::SEC installed") if $self->{"dnssec"} && ! $Net::DNS::DNSSEC; 1323 return $self->{"dnssec"}; 1324}; 1325 1326 1327 1328sub tsig { 1329 my $self = shift; 1330 1331 if (@_ == 1) { 1332 if ($_[0] && ref($_[0])) { 1333 $self->{'tsig_rr'} = $_[0]; 1334 } 1335 else { 1336 $self->{'tsig_rr'} = undef; 1337 } 1338 } 1339 elsif (@_ == 2) { 1340 my ($key_name, $key) = @_; 1341 $self->{'tsig_rr'} = Net::DNS::RR->new("$key_name TSIG $key"); 1342 } 1343 1344 return $self->{'tsig_rr'}; 1345} 1346 1347# 1348# Usage: $data = read_tcp($socket, $nbytes, $debug); 1349# 1350sub read_tcp { 1351 my ($sock, $nbytes, $debug) = @_; 1352 my $buf = ''; 1353 1354 while (length($buf) < $nbytes) { 1355 my $nread = $nbytes - length($buf); 1356 my $read_buf = ''; 1357 1358 print ";; read_tcp: expecting $nread bytes\n" if $debug; 1359 1360 # During some of my tests recv() returned undef even 1361 # though there wasn't an error. Checking for the amount 1362 # of data read appears to work around that problem. 1363 1364 unless ($sock->recv($read_buf, $nread)) { 1365 if (length($read_buf) < 1) { 1366 my $errstr = $!; 1367 1368 print ";; ERROR: read_tcp: recv failed: $!\n" 1369 if $debug; 1370 1371 if ($errstr eq 'Resource temporarily unavailable') { 1372 warn "ERROR: read_tcp: recv failed: $errstr\n"; 1373 warn "ERROR: try setting \$res->timeout(undef)\n"; 1374 } 1375 1376 last; 1377 } 1378 } 1379 1380 print ';; read_tcp: received ', length($read_buf), " bytes\n" 1381 if $debug; 1382 1383 last unless length($read_buf); 1384 $buf .= $read_buf; 1385 } 1386 1387 return $buf; 1388} 1389 1390 1391 1392sub _create_tcp_socket { 1393 my $self=shift; 1394 my $ns=shift; 1395 my $sock; 1396 1397 my $srcport = $self->{'srcport'}; 1398 my $srcaddr = $self->{'srcaddr'}; 1399 my $dstport = $self->{'port'}; 1400 1401 my $timeout = $self->{'tcp_timeout'}; 1402 # IO::Socket carps on errors if Perl's -w flag is 1403 # turned on. Uncomment the next two lines and the 1404 # line following the "new" call to turn off these 1405 # messages. 1406 1407 #my $old_wflag = $^W; 1408 #$^W = 0; 1409 1410 if ($has_inet6 && ! $self->force_v4() && _ip_is_ipv6($ns) ){ 1411 # XXX IO::Socket::INET6 fails in a cryptic way upon send() 1412 # on AIX5L if "0" is passed in as LocalAddr 1413 # $srcaddr="0" if $srcaddr eq "0.0.0.0"; # Otherwise the INET6 socket will just fail 1414 1415 my $srcaddr6 = $srcaddr eq '0.0.0.0' ? '::' : $srcaddr; 1416 1417 $sock = 1418 IO::Socket::INET6->new( 1419 PeerPort => $dstport, 1420 PeerAddr => $ns, 1421 LocalAddr => $srcaddr6, 1422 LocalPort => ($srcport || undef), 1423 Proto => 'tcp', 1424 Timeout => $timeout, 1425 ); 1426 1427 unless($sock){ 1428 $self->errorstring('connection failed(IPv6 socket failure)'); 1429 print ";; ERROR: send_tcp: IPv6 connection to $ns". 1430 "failed: $!\n" if $self->{'debug'}; 1431 return(); 1432 } 1433 } 1434 1435 # At this point we have sucessfully obtained an 1436 # INET6 socket to an IPv6 nameserver, or we are 1437 # running forced v4, or we do not have v6 at all. 1438 # Try v4. 1439 1440 unless($sock){ 1441 if (_ip_is_ipv6($ns)){ 1442 $self->errorstring( 1443 'connection failed (trying IPv6 nameserver without having IPv6)'); 1444 print 1445 ';; ERROR: send_tcp: You are trying to connect to '. 1446 $ns . " but you do not have IPv6 available\n" 1447 if $self->{'debug'}; 1448 return(); 1449 } 1450 1451 1452 $sock = IO::Socket::INET->new( 1453 PeerAddr => $ns, 1454 PeerPort => $dstport, 1455 LocalAddr => $srcaddr, 1456 LocalPort => ($srcport || undef), 1457 Proto => 'tcp', 1458 Timeout => $timeout 1459 ) 1460 } 1461 1462 #$^W = $old_wflag; 1463 1464 unless ($sock) { 1465 $self->errorstring('connection failed'); 1466 print ';; ERROR: send_tcp: connection ', 1467 "failed: $!\n" if $self->{'debug'}; 1468 return(); 1469 } 1470 1471 return $sock; 1472} 1473 1474 1475# Lightweight versions of subroutines from Net::IP module, recoded to fix rt#28198 1476 1477sub _ip_is_ipv4 { 1478 my @field = split /\./, shift; 1479 1480 return 0 if @field > 4; # too many fields 1481 return 0 if @field == 0; # no fields at all 1482 1483 foreach ( @field ) { 1484 return 0 unless /./; # reject if empty 1485 return 0 if /[^0-9]/; # reject non-digit 1486 return 0 if $_ > 255; # reject bad value 1487 } 1488 1489 1490 return 1; 1491} 1492 1493 1494sub _ip_is_ipv6 { 1495 1496 for ( shift ) { 1497 my @field = split /:/; # split into fields 1498 return 0 if (@field < 3) or (@field > 8); 1499 1500 return 0 if /::.*::/; # reject multiple :: 1501 1502 if ( /\./ ) { # IPv6:IPv4 1503 return 0 unless _ip_is_ipv4(pop @field); 1504 } 1505 1506 foreach ( @field ) { 1507 next unless /./; # skip :: 1508 return 0 if /[^0-9a-f]/i; # reject non-hexdigit 1509 return 0 if length $_ > 4; # reject bad value 1510 } 1511 } 1512 return 1; 1513} 1514 1515 1516 1517sub AUTOLOAD { 1518 my ($self) = @_; 1519 1520 my $name = $AUTOLOAD; 1521 $name =~ s/.*://; 1522 1523 Carp::croak "$name: no such method" unless exists $self->{$name}; 1524 1525 no strict q/refs/; 1526 1527 1528 *{$AUTOLOAD} = sub { 1529 my ($self, $new_val) = @_; 1530 1531 if (defined $new_val) { 1532 $self->{"$name"} = $new_val; 1533 } 1534 1535 return $self->{"$name"}; 1536 }; 1537 1538 1539 goto &{$AUTOLOAD}; 1540} 1541 15421; 1543 1544__END__ 1545 1546=head1 NAME 1547 1548Net::DNS::Resolver::Base - Common Resolver Class 1549 1550=head1 SYNOPSIS 1551 1552 use base qw/Net::DNS::Resolver::Base/; 1553 1554=head1 DESCRIPTION 1555 1556This class is the common base class for the different platform 1557sub-classes of L<Net::DNS::Resolver|Net::DNS::Resolver>. 1558 1559No user serviceable parts inside, see L<Net::DNS::Resolver|Net::DNS::Resolver> 1560for all your resolving needs. 1561 1562=head1 COPYRIGHT 1563 1564Copyright (c) 1997-2002 Michael Fuhr. 1565 1566Portions Copyright (c) 2002-2004 Chris Reinhardt. 1567Portions Copyright (c) 2005 Olaf Kolkman <olaf@net-dns.org> 1568Portions Copyright (c) 2006 Dick Franks. 1569 1570All rights reserved. This program is free software; you may redistribute 1571it and/or modify it under the same terms as Perl itself. 1572 1573=head1 SEE ALSO 1574 1575L<perl(1)>, L<Net::DNS>, L<Net::DNS::Resolver> 1576 1577=cut 1578 1579 1580