4.4BSD/usr/src/contrib/bind-4.9/contrib/decwrl/mkdb.pl

#! /usr/bin/perl
#
# $Header: mkdb,v 1.36 93/01/14 01:02:41 root Exp $
#
# from a hosts(5) database on standard input or argv,
# build the .data and .zone files needed by named.boot

#++ BEGIN user servicable parts
$Domain = 'pa.dec.com';
$Zone = 'decpa';
@Gateway_MX = (
	'10 pobox1',
	'20 inet-gw-1',
	'20 inet-gw-2'
);
#-- END user servicable parts (more later, though)

umask(022);
chop($date = `/bin/date`);
$Serial_File = 'version';
($Domain_Pat = "$Domain") =~ s/(\W)/\\$1/go;
$Domain_Pat = "\\.$Domain_Pat\$";

&Update_Serial_Number();
&Update_Zone_Serials();	
&Init_Zone_Datafiles();
&Churn();
&Close_Zone_Datafiles();

exit 0;

sub Write_RR {
	local($fh, $name, $type, $data) = @_;

	if ($name eq $Write_RR'last_name{$fh}) {
		$name = '';
	} else {
		$Write_RR'last_name{$fh} = $name;
	}
	printf $fh "%-30s in %-5s %s\n", $name, $type, $data;
}

sub Update_Serial_Number {
	local(*f);

	if (open(f, "<$Serial_File") && ($Serial_No = <f>)) {
		close(f);
	} else {
		$Serial_No = 0;
	}

	$Serial_No++;

	open(f, ">$Serial_File") || die "$Serial_File: $!";
	print f "$Serial_No\n";
	close(f);

	print "*** New serial number is $Serial_No\n";
}

sub Update_Zone_Serials {
	local(*f, $zonefile, $zone);

	foreach $zonefile (<*.zone>) {
		$zone = $zonefile;
		$zone =~ s/\.zone$//;
		$Zones{$zone}++ unless ($zone eq $Zone);
		print "*** updating zone file '$zonefile'\n";
		open(f, "<$zonefile") || die "$zonefile: $!";
		@f = <f>;
		open(f, ">$zonefile.NEW") || die "$zonefile.NEW: $!";
		foreach (@f) {
			$_ = $`.$Serial_No.$1."\n" if (/\d+(\s+\;Serial)/);
			print f;
		}
		close(f) || die "$zonefile.NEW: $!";
	}

	print "*** Zone file serial numbers updated\n";
}

sub Init_Zone_Datafiles {
	#
	# our name servers are considered authoritative for the following
	# zones of in-addr.arpa.  we create a .data file for each here.  None
	# of them have SOA's since we expect them to be $INCLUDE'd by .zone
	# files.
	#
	local($zone);

	foreach $zone (sort(keys(%Zones))) {
		print "*** Init'ing zone ".$zone."\n";
		open($zone, ">$zone.data.NEW") || die "$zone.data.NEW: $!";
		$rzone = join('.', reverse(split(/\./, $zone)))
		       . '.in-addr.arpa.';
		print $zone "; $zone.data ($zone - $rzone) $date\n";
		print $zone '$ORIGIN '.$rzone."\n";
	}

	# the main host->addr file has no origin statement in it since
	# its name is not mechanically translatable to its zone.
	open($Zone, ">$Zone.data.NEW") || die "$Zone.data.NEW: $!";
	foreach (@Gateway_MX) {
		&Write_RR($Zone, '@', 'mx', $_);
	}
}

sub Close_Zone_Datafiles {
	foreach ($Zone, keys(%Zones)) {
		close($_) || die "$_.data.NEW: $!";
		rename("$_.data", "$_.data.BAK");
		rename("$_.data.NEW", "$_.data") || die "rename1 ($_): $!";
		rename("$_.zone", "$_.zone.BAK");
		rename("$_.zone.NEW", "$_.zone") || die "rename2 ($_): $!";
	}
}

sub Churn {
    print "*** Churning\n";
host:
    while (<>) {
	chop;

	# capture and convert comments
	if (/^\s*\#/) {
		$_ = ';' . $';
		print $Zone "$_\n";
		last host if (/BELOW HERE NOT REGISTERED WITH DOMAIN SERVER/);
		next host;
	}
	s/\s*\#.*$//;

	# parse line, skip it if addr doesn't have four components
	y/A-Z/a-z/;
	($a, $name, @aliases) = split;
	next host if (4 != (@a = split(/\./, $a)));
	$name =~ s/$Domain_Pat//o;

	#
	# names that still have dots need to be qualified since they
	# aren't local.
	#
	# only local names get MX RR's generated for them.
	#
	if ($name =~ /\./) {
		$fullname = $name . '.';
	} else {
		&Write_RR($Zone, $name, 'a', $a);
		#
		# do not generate mx rr's for network or broadcast a rr's
		# or for loopback addresses
		#
		if ($a[0] != 127 && $a[3] != 0 && $a[3] != 255) {
			&Write_RR($Zone, $name, 'mx', "0 $name");
			foreach (@Gateway_MX) {
				&Write_RR($Zone, $name, 'mx', $_);
			}
		}
		$fullname = $name . ".$Domain.";
	}

	#++ BEGIN user servicable parts
	if ($a[0] == 16) {
		$zone = '16.' . $a[1];
		$ptr = $a[3] . '.' . $a[2];
	} else {
		$zone = 'bogus';
		$ptr = 'bogus';
	}
	#-- END user servicable parts

	#
	# if this is a zone we support, write out a PTR for it
	#
	if ($Zones{$zone}) {
		&Write_RR($zone, $ptr, 'ptr', $fullname);
	}

	#
	# iterate over the aliases, if any, and generate CNAMEs and PTRs.
	#
	foreach (@aliases) {
		s/$Domain_Pat//o;

		# aliases that are the same as the basename aren't useful
		next if ($_ eq $name);

		# CNAME makes sense only for local names
		if (! /\./) {
			$maybedot = '.' if ($name =~ /\./);
			&Write_RR($Zone, $_, 'cname', $name.$maybedot);
		}

		# PTR makes sense only for zones we support (NOTE: $_ smashed)
		if ($Zones{$zone}) {
			$_ .= ".$Domain" unless /\./;
			&Write_RR($zone, $ptr, 'ptr', "$_.");
		}
	}
    }
}