#!/usr/bin/perl

#
# This script quickly creates basic MaraDNS setup for use with the 
# Coda advanced networked filesystem, http://www.coda.cs.cmu.edu/ .
#
# You need to have MaraDNS installed, then just invoke this script
# and eventually edit choices when prompted, if the autodetection
# doesn't do everything on its own.
#
# All options can also be specified on the command line, names are
# identical (i.e. $domain variable is --domain on command line).
#
# Non-interactive mode doesn't prompt anything and just does its
# thing.
#
# Most common invocation: 
#  vice-setup-maradns --domain your.domain
#  vice-setup-maradns --domain your.domain --a2host a2 --noninteractive
#
# The script saves old configuration, but anyway if you just want to see
# what would the script do, invoke
#
#  vice-setup-maradns --maradir /tmp
#
# Davor Ocelic, docelic@hcoop.net, Sat Feb 10 16:16:02 CET 2007
#

use warnings;
use strict;

use File::Temp qw/tempfile tempdir/;
use Getopt::Long;

use constant DEBUG => 1;


print "\nProgram will perform some autodetection. Don't worry if you see
error messages, they won't stop execution and you'll be able to
tune the settings manually before the configuration takes place.\n";


# Discover network values. Not the best way to do it, but 
# works for me.
my $dnsname = qx{hostname}; chomp $dnsname;
   $dnsname =~ s/\..*//;

my $dnsip   = qx{ping -c 1 `hostname` | head -n 1 | awk '{ print \$3 }'}; # '
   $dnsip   =~ s/[()]//g; chomp $dnsip;
my @ip = ( $dnsip =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/ );

my $mask = qx{ifconfig -a};
	 $mask =~ s/\n?\w+\s+Link encap.*?\s+inet addr:$dnsip.*?Mask:([\d.]+).*/$1/s;
	 $mask ||= "255.255.255.0";

my $tmp  = $mask;
my @cidr = @ip;
my $bits;
my $cnt = -1;
while ( $tmp =~ s/\.0+$|\.0+\././ ) {
	$bits+= 8;
	splice @cidr, $cnt--, 1, 0;
}

my $cidr = (join '.', @cidr) . "/$bits";

my $domain;
if ( -r ( $_ = '/etc/domainname') )             { $domain = `cat $_` }
if ( -r ( $_ = '/proc/sys/kernel/domainname') ) { $domain = `cat $_`; }
chomp $domain;
$domain =~ s/\(none\)//;
$domain =~ /\S/ or $domain = "YOURDOMAIN";

my ($maradir, $codaname, $codaip, $a2name, $a2ip, $codaport, $a2port);
my $noninteractive;

# Use GetOpt to pick settings from command line
GetOptions (
	"maradir=s"  => \$maradir,
	"dnsname=s"  => \$dnsname,
	"dnsip=s"    => \$dnsip,
	"domain=s"   => \$domain,
	"codaname=s" => \$codaname,
	"codaip=s"   => \$codaip,
	"codaport=i" => \$codaport,
	"a2name=s"   => \$a2name,
	"a2ip=s"     => \$a2ip,
	"a2port=i"   => \$a2port,
	"mask=s"     => \$mask,
	"cidr=s"     => \$cidr,

	"noninteractive!" => \$noninteractive,
);


# Sanitize options, provide defaults unless specified
$maradir ||= "/etc/maradns/";

$codaname ||= $dnsname;
$a2name ||= $dnsname;

$codaip ||= $dnsip;
$a2ip ||= $dnsip;

$codaport ||= 2432;
$a2port ||= 370;


# Give out summary, offer manual intervention
my ($fh, $fn) = tempfile();
print $fh qq{
\$maradir	=   "$maradir"

\$dnsname	=   "$dnsname"
\$dnsip		=   "$dnsip"
\$domain		=   "$domain"

\$codaname	=   "$codaname"
\$codaip		=   "$codaip"
\$codaport	=   "$codaport"

\$a2name		=   "$a2name"
\$a2ip		=   "$a2ip"
\$a2port		=   "$a2port"

# Two not really important options
\$mask		=   "$mask"
\$cidr		=   "$cidr"
};
close $fh;

print `cat $fn`;

unless ( $noninteractive ) {
	print "\nWanna edit configuration? [y/N]: ";

	my $answer = <STDIN>;
	$answer =~ /[yds1]/i and system 'editor', $fn;
}


# Re-read settings from file which user might have edited
my @vars = `cat $fn`;
$_ .= ";" for @vars;
eval "@vars";


# Finally, go into filesystem change
# Make backup if needed:
if ( <$maradir/*> ) {
	my $tmpdir = tempdir( CLEANUP => 0, DIR => $maradir );
	print "Backing up existing configuration to '$tmpdir'\n";

	`cp $maradir/* $tmpdir/`;

	my $rc = "$maradir/mararc";
	my $db = "$maradir/db.$domain";

	my $date = scalar gmtime;

	print "\nWriting '$rc'...\n";
	open RC, "> $rc" or die "Can't wropen '$rc' ($!)\n";
	print RC qq{
# Generated by vice-setup-maradns on $date

ipv4_bind_addresses = "$dnsip,127.0.0.1"
chroot_dir = "$maradir"
recursive_acl = "$cidr"
csv2 = \{\}
csv2["$domain."] = "db.$domain"

};
	close RC or die "Can't wrclose '$rc' ($!)\n";

	print "Writing '$db'...\n";
	open DB, "> $db" or die "Can't wropen '$db' ($!)\n";
	print DB qq{
# Generated by vice-setup-maradns on $date

$codaname.$domain.            A      $codaip
$a2name.$domain.            A      $a2ip

_codasrv._udp.$domain.      SRV    0 0 $codaport       $codaname.$domain.
_codaauth2._udp.$domain.    SRV    0 0 $a2port        $a2name.$domain.

};
	close DB or die "Can't wrclose '$db' ($!)\n";
}

print "\nAll done. Restart your MaraDNS, then test configuration with:

askmara 33:_codasrv._udp.$domain.
askmara 33:_codaauth2._udp.$domain.
askmara A$codaname.$domain.

\n"; 

