#!/usr/bin/perl -wT

# Copyright 2002, 2003, 2004, 2005 Peter Palfrader <peter@palfrader.org>
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


=pod

=head1 NAME

makezonefile - create config file for bind

=head1 SYNOPSIS

makezonefile

=head1 DESCRIPTION

makezonefile reads from STDIN a list of domains and
their assoziated nameservers; one domain per line, the primary, the nameservers
seperated by whitespace.

Example:

  sigint.net 82.94.251.194  asteria.debian.or.at. seppia.noreply.org.
  theremailer.net 195.244.237.84|213.239.201.102  asteria.debian.or.at.
  vanderheide.ca 64.26.156.90  asteria.debian.or.at.

First column is the domain in question, second is the primary or primaries
separated by a pipe symbol, the rest are the nameservers

For each domain it will then look whether this host's name (as configured in
the @THISNAMES variable) appears in the list of nameservers and if that is the
case add a slave entry to the file hardcoded in the script.

Afterwards a bind9 reload will be issued.


The script is typicalle called from ssh (using authorized keys with command=script).

=head1 OPTIONS

none

=head1 AUTHOR

Peter Palfrader E<lt>peter@palfrader.org<gt>

=head1 FILES

/var/cache/bind/weasel/ldapzones.conf.slave.pushed

=head1 REQUIREMENTS

none but perl

=head1 SEE ALSO

Ask author.

=cut
	

use strict;
use English;

$ENV{'PATH'} = '/bin:/usr/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};

my $SOURCE_HOST = 'unknown';
if ($PROGRAM_NAME =~ m/-host-([a-z0-9]+)$/) {
	$SOURCE_HOST = $1;
};
my $NAMEDCONF = "/etc/bind/named.conf.from-$SOURCE_HOST.ldapzones.slave.pushed";
my @RELOAD = qw{/etc/init.d/bind9 reload};


my @THISNAMES;
my $CONFFILE = '/etc/noreply/make-bindconfig-from-ldap.conf';
if (-e $CONFFILE) {
	open(F, $CONFFILE) or die ("Cannot open $CONFFILE: $!\n");
	for my $line (<F>) {
		chomp($line);
		push @THISNAMES, $line;
	};
} else {
	my $fqdn = `hostname -f`;
	chomp $fqdn;
	$fqdn .= '.';
	push @THISNAMES, $fqdn;
};

my $date = localtime();
open (CONF, ">$NAMEDCONF") or
	die ("Cannot open $NAMEDCONF: $!\n");
print CONF << "EOF";
// conf file for bind
// $date
// automatically created by $PROGRAM_NAME from stdin (probably called by ssh)
// vim:set syn=named:
EOF
for my $thishost (@THISNAMES) {
	print CONF "// This system is known as $thishost\n";
};

my @lines = <>;
DOMAIN:
for my $line (@lines) {
	chomp ($line);
	my @part = split (/\s+/, $line);
	my $domain = shift @part;
	my @masters = split /\|/, shift @part;
	unless (defined $domain && ($domain =~ /^[a-z0-9.-]+$/)) {
		warn "Skipping $domain: bad name\n";
		next;
	};
	if (scalar @masters == 0) {
		warn "Skipping $domain: No masters\n";
		next;
	};
	for my $master (@masters) {
		unless (defined $master && ($master =~ /^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/)) {
			warn "Skipping $domain: bad master '$master'\n";
			next DOMAIN;
		};
	};
	my $this_ns = 0;
	for my $ns (@part) {
		for my $my_name (@THISNAMES) {
			$this_ns |= ($ns eq $my_name);
		};
	};
	next unless $this_ns;

	print CONF << "EOF";
	zone "$domain" {
		type slave;
		file "from-$SOURCE_HOST-slave-ldap-$domain";
		allow-transfer { "none"; };
		allow-query { any; };
		masters {
EOF
	for my $master (@masters) {
		print CONF "			$master;\n";
	};
	print CONF << "EOF";
		};
	};
EOF
};
close (CONF);

exec(@RELOAD);