--- lib/PXElator/dnsd.pm 2009/08/03 08:57:59 122 +++ lib/PXElator/dnsd.pm 2009/08/18 22:02:11 259 @@ -4,27 +4,95 @@ use strict; use Net::DNS::Nameserver; +use Net::DNS::Resolver; use Data::Dump qw/dump/; +use CouchDB; + +use server; +our $debug = server::debug; + +my $res = Net::DNS::Resolver->new( +# nameserver => [ '10.60.0.1' ], + recurse => 1, + debug => $debug, +); + +our $ptr_cache; +sub name_ip { + my ( $name, $ip ) = @_; + $ptr_cache->{ join('.', reverse split(/\./, $ip)) } = $name; + return $ip; +} sub reply_handler { my ($qname, $qclass, $qtype, $peerhost,$query,$conn) = @_; my ($rcode, @ans, @auth, @add); - print "Received query from $peerhost to ". $conn->{"sockhost"}. "\n"; - $query->print; + $debug = server::debug; + + my $audit = { + qname => $qname, + qclass => $qclass, + qtype => $qtype, + peerhost => $peerhost, + sockhost => $conn->{"sockhost"}, + source => 'unknown', + }; + + $query->print if $debug; + + my $local = $1 if $qname =~ m{^(.+)\.\Q$server::domain_name\E$}; + $local = $qname if $qname !~ m{\.}; - - if ($qtype eq "A" && $qname eq "foo.example.com" ) { - my ($ttl, $rdata) = (3600, "10.1.2.3"); - push @ans, Net::DNS::RR->new("$qname $ttl $qclass $qtype $rdata"); + my $ttl = 3600; + + if ( $local ) { + warn "local[$local] $qname $qtype"; $rcode = "NOERROR"; - }elsif( $qname eq "foo.example.com" ) { + my $rdata; + if ( $qtype eq "A" && $local eq "server" ) { + $rdata = name_ip( $local, $server::ip ); + $audit->{source} = 'local'; + } else { + $rcode = "NXDOMAIN"; + } + + push @ans, Net::DNS::RR->new("$qname $ttl $qclass $qtype $rdata") if $ttl; + + } elsif ( $qtype eq 'PTR' && $qname =~ m{^([0-9\.]*)\.in-addr\.arpa$} ) { + if ( my $rdata = $ptr_cache->{$1} ) { + $rdata .= '.' . $server::domain_name; + push @ans, Net::DNS::RR->new("$qname $ttl $qclass $qtype $rdata"); + $audit->{source} = 'PTR'; + } else { +warn "## ",dump( $ptr_cache ); + $rcode = "NXDOMAIN"; + } + } elsif ( my $packet = $res->query( $qname, $qtype ) ) { + + $audit->{source} = 'upstream'; + $packet->print; + push @ans, $_ foreach $packet->answer; $rcode = "NOERROR"; - }else{ - $rcode = "NXDOMAIN"; + } else { + # not found + $rcode = "NXDOMAIN"; } + warn "rcode: $rcode ",dump( @ans ); + + $audit->{rcode} = $rcode; + $audit->{ans} = [ map { + my $data; + foreach my $n ( keys %$_ ) { + $data->{$n} = $_->{$n}; + } + $data; + } @ans ]; + + CouchDB::audit( 'response', $audit ); + # mark the answer as authoritive (by setting the 'aa' flag return ($rcode, \@ans, \@auth, \@add, { aa => 1 }); } @@ -32,13 +100,17 @@ sub start { my $ns = Net::DNS::Nameserver->new( LocalPort => 53, - ReplyHandler => \&reply_handler, - Verbose => 1, + ReplyHandler => sub { + server->refresh; + reply_handler(@_); + }, + Verbose => $debug, ) || die "couldn't create nameserver object\n"; - warn dump( $ns ); + CouchDB::audit('start', { port => 53, domain_name => $server::domain_name }); + warn "DNS $server::domain_name"; $ns->main_loop; } -1; +1;