#!/usr/local/bin/perl

# bulkzone
# Create buld DNS entries in a slightly more intelligent fashion

#
# Pragmas
#

use strict;
use warnings;

#
# Includes
#

use Net::Netmask;

#
# Global Variables
#

use vars qw/$VERSION $Network $Reverse $Zone $Block $Opts /;

$VERSION=1.0;

#
# Subroutines
#

sub help
{
print <<EOHELP
Usage:  $0 --network "192.168.0.0/20"

Read the perldoc for information on all command line options.
EOHELP
;
}

sub cmdopts
{
my ($a);
while (@ARGV)
{
	($a)=shift(@ARGV);
	if ($a eq "--network")
	{
		$Network=shift(@ARGV);
	} elsif ($a eq "--reverse")
	{
		$Opts->{reverse}=1;
	} elsif ($a eq "--revzone")
	{
		$Opts->{revzone}=shift(@ARGV);
	} elsif ($a eq "--domain")
	{
		$Opts->{domain}=shift(@ARGV);
		unless ($Opts->{domain} =~ /^\./)
		{
			$Opts->{domain}=".".$Opts->{domain};
		}
		unless ($Opts->{domain} =~ /\.$/)
		{
			$Opts->{domain}.=".";
		}
	} elsif ($a eq "--prefix")
	{
		$Opts->{prefix}=shift(@ARGV);
	}
}
if ($Network)
{
	unless ($Network =~ /^\d+\.\d+\.\d+\.\d+\/\d+$/)
	{
		help();
		exit 2;
	}
} else {
	help();
	exit 2;
}
return;
}

sub display
{
my ($network,$opts)=@_;
my ($block);
$block=Net::Netmask->new($network);
if ($Opts->{reverse} || $Opts->{revzone})
{
	reverseZone($block,$opts);
} else {
	forwardZone($block,$opts);
}
return;
}

sub forwardZone
{
my ($block,$opts)=@_;
my ($index,$size,$host,$prefix,$fmt);
$size=$block->size()-2;
$fmt="%s\tIN\tA\t%s\n";
$index=1;
$prefix=$Opts->{prefix} || "h";
while ($index <= $size)
{
	$host=sprintf("%s%x",$prefix,$index);
	printf($fmt,$host,$block->nth($index));
	$index++;
}
return;
}

sub reverseZone
{
my ($block,$opts)=@_;
my ($zone,$start,$end,$prefix,$domain,$fmt,@data);
$fmt="%s\tIN\tPTR\t%s\n";
$prefix=$opts->{prefix} || "h";
$domain=$opts->{domain} || "";
(@data)=$block->inaddr();
while (($zone,$start,$end)=splice(@data,0,3))
{
	if ($Opts->{revzone})
	{
		next unless ($zone eq $Opts->{revzone});
	}
	my ($network,$loop,$ip,$order,$host);
	$network=revIp($zone);
	print(";Reverse Zone: $zone\n\n");
	for ($loop=$start;$loop<=$end;$loop++)
	{
		$ip="$network.$loop";
		next if ($block->base eq $ip || 
			$block->broadcast eq $ip);
		$order=$block->match($ip);
		$host=sprintf("%s%x%s",$prefix,$order,$domain);
		printf($fmt,$loop,$host);
	}
}
return;
}

sub revIp
{
my ($zone)=shift;
my ($network,@rz,@ipc);
(@rz)=split(/\./,$zone);
(@ipc)=reverse(splice(@rz,0,3));
$network=join(".",@ipc);
return $network;
}



#
# Main Program
#

# See what command line options are passed to us
cmdopts();

# Once the network is determined, start the loop

display($Network,$Opts);

#
# Exit Block
#
1;

#
# POD
#

=head1 NAME

=head1 SYNOPSIS

 $ bulkzone.pl --network 10.0.10.0/20 > dnsfile

=head1 DESCRIPTION

Bulkzone is used to create large pools of DNS entries for a nameserver 
zonefile.  Anyone needing to create matching forward and reverse DNS 
entries for large netblocks may want to ue bulkzone to automate the task.

Bulkzone only creates unique entries based on the host portion of an IP 
address.  If you have three large netblocks, you should not merge the entries 
from three different bulkzone runs together.  Each batch of entries 
should be in a seperate DNS zone, otherwise you will have conflicting 
host records.

Bulkzone was based on an article written on www.perl.com about how to 
automate the creation of DNS records necessary to facilitate 
forward and reverse DNS authentication.

=head1 OPTIONS

=over 4

=item --netmask [network in CIDR notation]

Identifies the network to create entries for.  

=item --reverse

Creates reverse PTR records instead of A records.

=item --revzone [domain]

Creates reverse PTR records only for a specified zone.  If the domain 
is outside of the network range, no output is given.

=item --zoneid

Creates 2 A records for the zone itself, set to the network address and 
the broadcast address of the block.

=item --prefix [string]

Appends a string prefix to the record.  By default a prefix of "h" is 
used.

=item --domain [string]

For creating PTR records, identifies the domain the record belongs in.

=back

=head1 AUTHOR

Chris Josephes, E<lt>chrisj@onvoy.comE<gt>

=head1 README

Bulkzone is a program that creates bulk DNS records, with a little 
intelligence.

=head1 PREREQUISITES

This program requires C<Net::Netmask> which is available on CPAN.

=head1 SCRIPT CATEGORIES

You can find this script in the CPAN scripts archive, under the 
C<Networking> and C<Unix:System administration> categories.

=head1 COPYRIGHT

Copyright 2002, Chris Josephes.  All rights reserved.  This program is 
free software.  It may be used, redistributed, and/or modified under 
the same terms as Perl itself.