#!/usr/local/bin/perl

# Copyright (C) 1996, David Muir Sharnoff

# Documentation is at the end of the file

$nslookup = "nslookup";
$named_pid = "/var/run/named.pid";
$zonefiles = "/etc/named";
$prefix = "second/";

$VERSION = 1.0;

@zones = @ARGV;

for $zone (@zones) {
	open(Z, ">$zonefiles/$zone.new")
		|| die "open > $zonefiles/$zone.new: $!";
	
	print Z "; This file was built automatically by ZMASTER\n";

	open(T,">/tmp/zmaster$$") 
		|| die "open > /tmp/zmaster$$: $!\n";
	print T "server ns.$zone.\n";
	print T "ls $zone.\n";
	close(T);

	$good = 0;
	open(NSLOOKUP,"$nslookup < /tmp/zmaster$$ 2>&1 |") 
		|| die "open nslookup: $!";
	while(<NSLOOKUP>) {
#chop;
#print "-$_-\n";
		next unless /^\> \[/;
		last;
	}
	unlink("/tmp/zmaster$$");
	while(<NSLOOKUP>) {
#print;
		next unless /^ (\S+[^.\s])\s+(\d+\.\d+\.\d+\.\d+)\s*$/;
		($domain, $server) = ($1, $2);
		next if $domain !~ /\./;
		$good = 1;
		(print Z "secondary	$domain	$server	$prefix$domain\n")
			|| die "print $zonefiles/$zone.new: $!";
		push(@nz, "secondary	$domain	$server	$prefix$domain\n");
	}
	close(NSLOOKUP);
	close(Z) || die "close $zonefiles/$zone.new: $!";

	die "invalid transfer of $zone" unless $good;

	if (-e "$zonefiles/$zone.boot") {
		open(OZ, "< $zonefiles/$zone.boot")
			|| die "open $zonefiles/$zone.boot: $!";
		$same = 1;
		while(<OZ>) {
			next if $_ eq unshift(@nz);
			$same = 0;
			last;
		}
		close(OZ);
		if ($same) {
			unlink("$zonefiles/$zone.new");
			next;
		}
	}

	rename("$zonefiles/$zone.new", "$zonefiles/$zone.boot")
		|| die "rename $zonefiles/$zone.new $zonefiles/$zone.boot: $!";

	$modified = 1;

	if ($named_pid) {
		open(P, "<$named_pid")
			|| die "open $named_pid: $!";
		chop($pid = <P>);
		close(P);
		if ($pid) {
			kill(1, $pid) 
				|| die "kill -1 $pid: $!";
		}
	} 
}

print STDERR "Please restart the nameserver\n"
	if $modified && ! $named_pid;

__END__

=head1 NAME

 zmaster -- automatically maintain nameserver zone files

=head1 SYNOPSIS

 zmaster special-zone-name

=head1 DESCRIPTION

 Zmaster is a tool for maintaining named.boot include files.  It is 
 meant to be run periodically on secondary name servers so that they 
 can automatically discover what zones (domains) they should be transfering
 (secondarying) from the primary server.

 To do this, the primary server must tell them which domains to take.
 This is done by creating a special zone that can be listed to find
 out which zones should be taken.

 In this special zone, there should be a host called 'ns'.  This host
 should have an A record that specifies a nameserver that can provide
 a listing of the hosts in the special domain.

=head1 EXAMPLES

 The following examples should illistrate what's required to run this.

=head2 named.boot

 In the named.boot file on the secondary system, include a line like:

 include /etc/named/ns2.idiom.com.boot

 In the named.boot file on the primary system, include a line like:

 primary ns2.idiom.com ns2.idiom.com

=head2 special zone file

 In the special zone file, in this case, ns2.idiom.com, include the 
 following:

 $ORIGIN ns2.idiom.com.
 @	 IN	 SOA	 idiom.com.	 muir.idiom.com. (
			 1996031908 86400 3600 2592000 86400 
			 )
	 IN	 NS	 ns.idiom.com.
	 IN	 NS	 ns3.idiom.com.
 @			 IN	 A	 206.80.31.66
 ns			 IN	 A	 140.174.82.4
 dream.com		 IN	 A	 140.174.82.4
 truedev.com		 IN	 A	 140.174.82.4

 This establishes that two domains (dream.com and truedev.com) are to
 be transfered.  They are to be transfered from the address given in the
 corrosponding A record.  The listing of this information will come from
 ns.ns2.idiom.com.  In addition, there is a host, ns2.idiom.com defined
 that will be ignored by zmaster.

=head1 AUTHOR

 David Muir Sharnoff, <muir@idiom.com>

=head1 ADVERTISEMENT
 
 Idiom will secondary domains for other ISPs for $0.50/month each.   There
 is a minimum purchase of 30 domains.  Send mail to support@idiom.com
 or visit http://www.idiom.com/secondary.shtml for more information.