use utf8;
use warnings; no warnings "redefine";
use strict;
use utf8;
use Net::DNS::Update;
use Dbase::Help qw(DoFn);
use Cf qw($NSI $NSI_KEY_NAME $NSI_KEY);
use Loader qw(get_rcode_info);
use Dbase::IP;
use Fehler qw(problem);

my $res = new Net::DNS::Resolver;
$res->nameservers($NSI);

## Idee: Die PTRs des Adressbereichs A werden als CNAMEs auf die Domain
##       B umgelenkt. 
#   Flag&7: wieviele IP-Adressteile verwendet werden sollen(+1)
#   Flag&8: im Ziel die Adressen umdrehen
#   Flag&16: Nimm die Teile raus, nicht rein.
##  

sub serve_cname($$;$) {
	return if $ENV{'TESTING3'};
	my($id,$domain,$flag) = @_;

	my $text = DoFn("select domain from domainkunde where id = $id");
	my $type = "MX";

	my($ip,$bits) = DoFn("select ip6,bits from ipkunde where id = $id");
	return undef unless defined $bits;
	$ip = Dbase::IP->new_db($ip,$bits);
	return problem "Das ist keine IPv4-Adresse"
		if not $ip->is_v4;
	return problem "Das geht nur bei einer Einzeladresse!\n"
		if $bits and $flag&3 == 0;
	return problem "Das geht nur bei max. einem /24er-Netz!\n"
		if $bits > 8 and $flag&3 == 1;
	return problem "Das geht nur bei max. einem /16er-Netz!\n"
		if $bits > 16 and $flag&3 == 2;
	return problem "Das geht nur bei max. einem /8er-Netz!\n"
		if $bits > 24 and $flag&3 == 3;
	
	my $idx = -1;
	$bits = 1<<$bits;
	$ip = $ip->bitmask(0);

	while($bits--) {
		my $addr = $ip->str;

		my(@alist)=($addr =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/);
		my $rptr = $ip->revstr;
		splice(@alist,0,4-($flag&7));
		@alist = reverse @alist if $flag & 8;
		my $text .= join(".",@alist);
		$text .= "." if $text ne "";
		$text .= "$domain";
		
		my $rzone = $rptr;
		while(1) {
			my $query = $res->query($rzone, "SOA");
			last if $query and $query->{'answer'}[0]{'type'} eq "SOA";
			next if $rzone =~ s/^[^\.]+\.//;
			warn "Kein SOA für $addr gefunden!\n"
				unless $ENV{'TESTING2'};
			return undef;
		}
		my $packet = new Net::DNS::Update($rzone);

		$packet->push("pre", new Net::DNS::RR(
			Name  => $rptr, Class => "IN", Type  => "CNAME",
			cname => $text, TTL => 0)) if $flag&16;
		$packet->push("pre", new Net::DNS::RR(
			Name  => $rptr, Class => "NONE", Type  => "ANY",
			TTL => 0)) if not $flag&16;

		$packet->push("update", new Net::DNS::RR(
			Name  => $rptr, Class => "ANY", Type  => "ANY", TTL => 0));

		$packet->push("update", new Net::DNS::RR(
			Name  => $rptr, Class => "IN", Type  => "CNAME",
			cname => $text, TTL => 24*3600)) if not $flag&16;

		$packet->sign_tsig($NSI_KEY_NAME, $NSI_KEY) if $NSI_KEY_NAME && $NSI_KEY;

		my $ans = $res->send($packet);

		if (defined $ans) {
			my $rcode = $ans->header->rcode;
			my $rcode_info = get_rcode_info $rcode;
			print "$addr => $text: $rcode",
			      defined $rcode_info && " ($rcode_info)",
			      "\n";
		} else {
			print "$addr => $text: FEHLER: ",$res->errorstring, "\n";
		}
	} continue {
		$ip++;
	}

}
1;

