#!/usr/local/bin/perl
# create_slave.cgi
# Create a new slave zone
# Modified by Howard Wilkinson <howard@cohtech.co.uk> 7th NOvember 2001
#        Added a facility to create a slave zone with the master(s)
#        on a non-standard port

require './bind8-lib.pl';
&ReadParse();
&error_setup($in{'type'} ? $text{'screate_err1'} : $text{'screate_err2'});
%access = &get_module_acl();
$access{'slave'} || &error($in{'type'} ? $text{'screate_ecannot1'}
				       : $text{'screate_ecannot2'});
$access{'ro'} && &error($text{'master_ero'});
$conf = &get_config();
$vconf = $in{'view'} ne '' ? $conf->[$in{'view'}]->{'members'} : $conf;

# validate inputs
if ($in{'rev'}) {
	local($ipv4);
	($ipv4 = &check_net_ip($in{'zone'})) ||
	$config{'support_aaaa'} &&
	($in{'zone'} =~ /^([\w:]+)(\/\d+)$/ || &check_ip6address($1)) ||
                &error(&text('create_enet', $in{'zone'}));
	if ($ipv4) {
		$in{'zone'} = &ip_to_arpa($in{'zone'});
		}
	else {
		$in{'zone'} = &net_to_ip6int($1, ($2 ? substr($2, 1) : "" ));
		}
	}
else {
	($in{'zone'} =~ /^[\d\.]+$/ || $in{'zone'} =~ /^[\d\:]+(\/[\d]+)?$/) &&
		&error(&text('create_edom2', $in{'zone'}));
	&valdnsname($in{'zone'}, 0, ".") ||
		&error(&text('create_edom', $in{'zone'}));
        }
$in{'zone'} =~ s/\.$//;
foreach $z (&find("zone", $vconf)) {
	if ($z->{'value'} eq $in{'zone'}) {
		&error($text{'master_etaken'});
		}
	}
$masterport = $in{'port_def'} ? undef : $in{'port'};
@masters = split(/\s+/, $in{'masters'});
foreach $m (@masters) {
	&check_ipaddress($m) ||
		&error(&text('create_emaster', $m));
	}
if (!@masters) {
	&error($text{'create_enone'});
	}
$base = $config{'slave_dir'} ? $config{'slave_dir'} :
	$access{'dir'} eq '/' ? &base_directory($conf) :
				$access{'dir'};
$base =~ s/\/+$// if ($base ne '/');
if ($in{'file_def'} == 0) {
	# Use the entered filename
	$in{'file'} =~ /^\S+$/ ||
		&error(&text('create_efile', $in{'file'}));
	$in{'file'} =~ s/^$config{'chroot'}//;
	if ($in{'file'} !~ /^\//) {
		$file = $base."/".$in{'file'};
		}
	else { $file = $in{'file'}; }
	&allowed_zone_file(\%access, $file) ||
		&error(&text('create_efile2', $file));
	open(ZONE, "> $config{'chroot'}$file") ||
		&error(&text('create_efile3', $file, $!));
	close(ZONE);
	&set_ownership("$config{'chroot'}$file");
	}
elsif ($in{'file_def'} == 2) {
	if ($in{'rev'}) {
		# create filename for reverse zone
		$file = &ip6int_to_net(&arpa_to_ip($in{'zone'}));
		$file =~ s/\//_/;
		local $format = $config{'reversezonefilename_format'};
		$format =~ s/ZONE/$file/g;
		$file = $base."/".$format;
		}
	else {
		# create filename for forward zone
		local $format = $config{'forwardzonefilename_format'};
		$format =~ s/ZONE/$in{'zone'}/g;
		$file = $base."/".$format;
		}
	open(ZONE, "> $config{'chroot'}$file") ||
		&error(&text('create_efile3', $file, $!));
	close(ZONE);
	&set_ownership("$config{'chroot'}$file");
	}

# Create zone directive
if ($in{'view'} ne '') {
	$view = $conf->[$in{'view'}];
	&lock_file($config{'chroot'}.$view->{'file'});
	@mdirs = map { { 'name' => $_ } } @masters;
	$masters = { 'name' => 'masters',
		     'type' => 1,
		     'members' => \@mdirs };
	if (defined($masterport)) {
	  $masters->{'values'} = [ 'port', $masterport ];
	}
	$dir = { 'name' => 'zone',
		 'values' => [ $in{'zone'} ],
		 'type' => 1,
		 'members' => [ { 'name' => 'type',
				  'values' => [ $in{'type'} ? 'slave'
							    : 'stub' ] },
				$masters
			      ]
		};
	if ($file) {
		push(@{$dir->{'members'}},
			{ 'name' => 'file',
			  'values' => [ $file ] });
		}
	&save_directive($view, undef, [ $dir ], 1);
	&flush_file_lines();
	&unlock_file($config{'chroot'}.$view->{'file'});
	}
else {
	$named_conf = $config{'zones_file'} ? $config{'zones_file'}
					    : $config{'named_conf'};
	&lock_file($config{'chroot'}.$named_conf);
	open(CONF, ">>$config{'chroot'}$named_conf");
	print CONF "zone \"$in{'zone'}\" {\n";
	print CONF "\ttype ",$in{'type'} ? 'slave' : 'stub',";\n";
	if ($file) { print CONF "\tfile \"$file\";\n"; }
	if (defined($masterport)) {
	  print CONF "\tmasters port $masterport {\n";
	} else {
	  print CONF "\tmasters {\n";
	}
	foreach $m (@masters) { print CONF "\t\t$m;\n"; }
	print CONF "\t\t};\n";
	print CONF "\t};\n";
	print CONF "\n";
	close(CONF);
	&unlock_file($config{'chroot'}.$named_conf);
	}
&webmin_log("create", $in{'type'} ? 'slave' : 'stub', $in{'zone'}, \%in);

# Add the new zone to the access list
if ($access{'zones'} ne '*') {
	$access{'zones'} .= " ".$in{'zone'};
	&save_module_acl(\%access);
	}
undef(@get_config_cache);
$conf = &get_config();
foreach $c (@$conf) {
	if ($c->{'name'} eq 'zone' && $c->{'value'} eq $in{'zone'}) {
		$idx = $c->{'index'};
		}
	}
&redirect(defined($idx) ? $in{'type'} ? "edit_slave.cgi?index=$idx" :
			"edit_stub.cgi?index=$idx" : "index.cgi");

