AnyEvent

 view release on metacpan or  search on metacpan

lib/AnyEvent/DNS.pm  view on Meta::CPAN

               # debug, rotate, no-check-names, inet6
            }
         }
      } else {
         # silently skip stuff we don't understand
      }
   }

   $self->{timeout} = [($self->{timeout}[0]) x $attempts]
      if $attempts;

   $self->_compile;
}

sub _load_resolv_conf_file {
   my ($self, $resolv_conf) = @_;

   $self->_config_begin;

   require AnyEvent::IO;
   AnyEvent::IO::aio_load ($resolv_conf, sub {
      if (my ($contents) = @_) {
         $self->parse_resolv_conf ($contents);
      } else {
         AE::log 4 => "$resolv_conf: $!";
      }

      $self->_config_done;
   });
}

=item $resolver->os_config

Tries so load and parse F</etc/resolv.conf> on portable operating
systems. Tries various egregious hacks on windows to force the DNS servers
and searchlist out of the system.

This method must be called at most once before trying to resolve anything.

=cut

sub os_config {
   my ($self) = @_;

   $self->_config_begin;

   $self->{server} = [];
   $self->{search} = [];

   if ((AnyEvent::WIN32 || $^O =~ /cygwin/i)) {
      # TODO: this blocks the program, but should not, but I
      # am too lazy to implement and test it. need to boot windows. ugh.

      #no strict 'refs';

      # there are many options to find the current nameservers etc. on windows
      # all of them don't work consistently:
      # - the registry thing needs separate code on win32 native vs. cygwin
      # - the registry layout differs between windows versions
      # - calling windows api functions doesn't work on cygwin
      # - ipconfig uses locale-specific messages

      # we use Net::DNS::Resolver first, and if it fails, will fall back to
      # ipconfig parsing.
      unless (eval {
         # Net::DNS::Resolver uses a LOT of ram (~10mb), but what can we do :/
         # (this seems mostly to be due to Win32::API).
         require Net::DNS::Resolver;
         my $r = Net::DNS::Resolver->new;

         $r->nameservers
            or die;

         for my $s ($r->nameservers) {
            if (my $ipn = AnyEvent::Socket::parse_address ($s)) {
               push @{ $self->{server} }, $ipn;
            }
         }
         $self->{search} = [$r->searchlist];

         1
      }) {
         # we use ipconfig parsing because, despite all its brokenness,
         # it seems quite stable in practise.
         # unfortunately it wants a console window.
         # for good measure, we append a fallback nameserver to our list.

         if (open my $fh, "ipconfig /all |") {
            # parsing strategy: we go through the output and look for
            # :-lines with DNS in them. everything in those is regarded as
            # either a nameserver (if it parses as an ip address), or a suffix
            # (all else).

            my $dns;
            local $_;
            while (<$fh>) {
               if (s/^\s.*\bdns\b.*://i) {
                  $dns = 1;
               } elsif (/^\S/ || /^\s[^:]{16,}: /) {
                  $dns = 0;
               }
               if ($dns && /^\s*(\S+)\s*$/) {
                  my $s = $1;
                  $s =~ s/%\d+(?!\S)//; # get rid of ipv6 scope id
                  if (my $ipn = AnyEvent::Socket::parse_address ($s)) {
                     push @{ $self->{server} }, $ipn;
                  } else {
                     push @{ $self->{search} }, $s;
                  }
               }
            }
         }
      }

      # always add the fallback servers on windows
      push @{ $self->{server} }, @DNS_FALLBACK;

      $self->_config_done;
   } else {
      # try /etc/resolv.conf everywhere else



( run in 1.650 second using v1.01-cache-2.11-cpan-ceb78f64989 )