#!/usr/bin/perl -W # (P) & (C) 2006 by Peter Bieringer # Perl demonstration program how getaddrinfo should resolve addresses for a name in a proper way # 20060827/PB: initial # 20060828/PB: implement SOA check for domain (in case of no search domain is used), replace "search" with "query" # TODO: # - configurable options use Net::DNS; my @search_domains; # Get search domains sub get_search_domains() { open (RESOLVCONF, "< /etc/resolv.conf") || die "Can't open /etc/resolv.conf"; while () { chomp ($_); my ($token, @values) = split / /, $_; if (defined $token && $token eq "search") { push @search_domains, @values; }; }; close (RESOLVCONF); print "Found following search domains:\n"; for my $search_domain (@search_domains) { print " " . $search_domain . "\n"; }; }; get_search_domains(); my $host = $ARGV[0]; if (! defined $host || $host eq "") { die "Missing host to resolv (arg1)"; }; my @resolv_result; my $flag_have_result = 0; my $flag_have_noerror = 0; my $flag_have_ipv4 = 0; my $flag_have_ipv6 = 0; my $flag_have_soa = 0; print "\nStart lookup(s)\n"; for my $search_domain ("", @search_domains) { my $lookup_host = $host . "." . $search_domain; print " Lookup: " . $lookup_host . "\n"; my $res = Net::DNS::Resolver->new(dnsrch => 0, defnames => 0); # AAAA query my $query = $res->query($lookup_host, "AAAA"); print " Query: " . $lookup_host . " AAAA\n"; if ($query) { $flag_have_result = 1; foreach my $rr ($query->answer) { next unless($rr->type eq "AAAA"); print " Result: " . $rr->type . " " . $rr->address . "\n"; push @resolv_result, $rr->type . " " . $rr->address; $flag_have_ipv6 = 1; } } else { warn " Query failed: ", $res->errorstring, "\n"; if ($res->errorstring eq "NOERROR") { $flag_have_noerror = 1; }; }; # A query $query = $res->query($lookup_host, "A"); print " Query: " . $lookup_host . " A\n"; if ($query) { $flag_have_result = 1; foreach my $rr ($query->answer) { next unless($rr->type eq "A"); print " Result: " . $rr->type . " " . $rr->address . "\n"; push @resolv_result, $rr->type . " " . $rr->address; $flag_have_ipv4 = 1; } } else { warn " Query failed: ", $res->errorstring, "\n"; if ($res->errorstring eq "NOERROR") { $flag_have_noerror = 1; }; }; if ($flag_have_result || $flag_have_noerror) { goto ("LABEL_end"); }; if ($search_domain ne "") { # a search domain is used, try next one next; }; # no search domain is currently used if (scalar(@search_domains) == 0) { # also none are given, so SOA check can be skipped at all goto ("LABEL_end"); }; # NXDOMAIN doesn't differ between "host not exists" and "domain not exists" # check for SOA of used domain now my $domain = $lookup_host; while (1 == 1) { # strip 1st part $domain =~ /^[^.]+\.(.*)$/; $domain = $1; if (!defined $domain || $domain eq "") { last; }; $query = $res->query($domain, "SOA"); print " Query: " . $domain . " SOA\n"; if ($query) { foreach my $rr ($query->answer) { next unless($rr->type eq "SOA"); print " Result: " . $rr->type . " " . $rr->string . "\n"; push @resolv_result, $rr->type . " " . $rr->string; $flag_have_soa = 1; } } else { warn " Query failed: ", $res->errorstring, "\n"; if ($res->errorstring eq "NOERROR") { $flag_have_noerror = 1; }; }; if ($flag_have_soa || $flag_have_noerror) { goto ("LABEL_end"); }; }; }; LABEL_end: print "\nResult:\n"; print " Flags:\n"; print " flag_have_result=" . $flag_have_result . "\n"; print " flag_have_noerror=" . $flag_have_noerror . "\n"; print " flag_have_ipv4=" . $flag_have_ipv4 . "\n"; print " flag_have_ipv6=" . $flag_have_ipv6 . "\n"; print " flag_have_soa=" . $flag_have_soa . "\n"; print " DNS resolver result:\n"; if ($flag_have_noerror) { print " NOERROR\n"; } elsif ($flag_have_result) { print " SUCCESS\n"; } elsif ($flag_have_soa) { print " NXDOMAIN\n"; } elsif ($flag_have_soa == 0 && $flag_have_result == 0) { print " NXDOMAIN\n"; }; print " DNS resolver result details:\n"; foreach my $result (@resolv_result) { print " " . $result . "\n"; };