#!/usr/bin/perl  -I/usr/local/sauron
#
# generatehosts - utility to add host records
#
# Copyright (c) Michal Kostenec <kostenec@civ.zcu.cz> 2013-2014.
# Copyright (c) Timo Kokkonen <tjko@iki.fi>  2001-2004.
# $Id: generatehosts,v 1.9 2004/10/28 07:12:41 tjko Exp $
#
require 5;
use Getopt::Long;
use Net::Netmask;
use Sauron::DB;
use Sauron::Util;
use Sauron::BackEnd;
use Sauron::Sauron;
use Net::IP qw(:PROC);

load_config();

#######################################################################

sub tag_expand($) {
  my($str) = @_;
  my($i2,$i3,$i4,$ip1,$ip2,$ip3,$ip4);

  return '' if ($str =~ /^\s*$/);

  $i1=$i+$seq_start;
  $i2=sprintf("%02d",$i1);
  $i3=sprintf("%03d",$i1);
  $i4=sprintf("%04d",$i1);

  if ($ip =~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/) {
    $ip1=sprintf("%03d",$1);
    $ip2=sprintf("%03d",$2);
    $ip3=sprintf("%03d",$3);
    $ip4=sprintf("%03d",$4);
    $str=~ s/:IP1:/$ip1/g;
    $str=~ s/:IP2:/$ip2/g;
    $str=~ s/:IP3:/$ip3/g;
    $str=~ s/:IP4:/$ip4/g;
  }
  elsif ($ip =~ /^([0-9a-fA-F]{4}\:){4}([0-9a-fA-F]{4})\:([0-9a-fA-F]{4})\:([0-9a-fA-F]{4})\:([0-9a-fA-F]{4})$/) {
    $ip1=sprintf("%04s",$2);
    $ip2=sprintf("%04s",$3);
    $ip3=sprintf("%04s",$4);
    $ip4=sprintf("%04s",$5);
    $str=~ s/:IP1:/$ip1/g;
    $str=~ s/:IP2:/$ip2/g;
    $str=~ s/:IP3:/$ip3/g;
    $str=~ s/:IP4:/$ip4/g;
  }

  $str =~ s/:N:/$i1/g;
  $str =~ s/:N2:/$i2/g;
  $str =~ s/:N3:/$i3/g;
  $str =~ s/:N4:/$i4/g;
  return $str;
}

######################################################################

$user = (getpwuid($<))[0];
set_muser($user);

GetOptions("help|h","name=s","commit","noreverse","seqstart=s",
	   "outofzone","verbose","group=s","info=s");

if ($opt_help || @ARGV < 5) {
  print "syntax: $0 <server> <zone> <hostname> <starting-IP> <count>\n\n",
        "options:\n",
	"\t--noreverse\t\tdo not add reverse records\n",
	"\t--outofzone\t\tallow out of zone records\n",
	"\t--verbose\t\tproduce more verbose output\n",
	"\t--seqstart=<n>\t\tstart sequence numbering from n\n",
	"\t--group=<name>\t\tassign new hosts to given group\n",
	"\t--info=<user>:<dept>:<location>:<extra>\n\n",
	"\t--commit\t\tcommit changes (w/o this no changes are made)\n",
	"\nIPv4 tags:\n",
    "\n",
	"\t:IP1:\t\tfirst octet of current IP-number\n",
	"\t:IP2:\t\tsecond octet of current IP-number\n",
	"\t:IP3:\t\tthird octet of current IP-number\n",
	"\t:IP4:\t\tfourth octet of current IP-number\n",
	"\t:N:\t\tsequence number\n",
	"\n",
    "\nIPv6 tags:\n",
    "\n",
	"\t:IP1:\t\tfifth hextet of current IP-number\n",
	"\t:IP2:\t\tsixth hextet of current IP-number\n",
	"\t:IP3:\t\tseventh hextet of current IP-number\n",
	"\t:IP4:\t\teighth hextet of current IP-number\n",
	"\t:N:\t\tsequence number\n",
	"\n";

  print "" if ($opt_help);
  exit(0);
}

$opt_commit = ($opt_commit ? 1 : 0);
$opt_noreverse = ($opt_noreverse ? 1 : 0);

$server=$ARGV[0];
$zone=$ARGV[1];
$hostname=$ARGV[2];
$startip=$ARGV[3];
$count=$ARGV[4];
$gid=-1;
$seq_start=0;
$add_count=0;


db_connect();

if ($opt_seqstart) {
  $seq_start = $opt_seqstart;
  fatal("invalid parameter to 'seq-start'") unless ($seq_start =~ /^\d+$/);
}

$serverid=get_server_id($server);
fatal("cannot find server '$server'") unless ($serverid > 0);

$zoneid=get_zone_id($zone,$serverid);
fatal("cannot find zone '$zone'") unless ($zoneid > 0);

if ($opt_group) {
  fatal("cannot find group '$opt_group'") 
    if (($gid=get_group_by_name($serverid,$opt_group)) < 0);
}

if ($opt_info) {
  @infof = split(/:/,$opt_info);
  fatal("invalid paremeters for info option ") if (@infof > 4);
}

fatal("invalid 'count' parameter: $count") unless ($count > 0);
fatal("invalid 'hostname' parameter: '$hostname'") 
	  unless ($hostname =~ /^\S+$/);
fatal("invalid 'starting-IP' parameter: $startip") unless (is_cidr($startip));


my $range = new Net::IP("$startip + " . ($count - 1)) or fatal("cannot create range variable");

$origin=$zone;
$origin.="." unless ($zone =~ /\.$/);

my $family = (ip_is_ipv4($startip) ? 4 : 6);
print "IP range: " . $startip . " - ". ip_compress_address($range->last_ip(), $family) . "\n" if ($opt_verbose);


db_begin();
db_ignore_begin_and_commit(1);

$i = 0;

do {
  $ip = $range->ip();
  $ip_c = ip_compress_address($range->ip(), $family);
  $domain=tag_expand($hostname);
  $host=remove_origin($domain,$origin);
  
  print "$host : " . $ip_c . " \n";

  undef @q;
  db_query("SELECT id FROM hosts WHERE zone=$zoneid AND domain = '$host';",
	   \@q);
  if (defined $q[0][0] and ($id=$q[0][0]) > 0) {
    fatal("host: $host already exists!");
  }

  undef %host;
  $host{domain}=$host;
  $host{type}=1;
  $host{zone}=$zoneid;
  $host{grp}=$gid;
  $host{ip}=[[0,$ip_c,'t',($opt_noreverse ? 'f' : 't')]];
  $host{huser}=tag_expand($infof[0]) if ($infof[0]);
  $host{dept}=tag_expand($infof[1]) if($infof[1]);
  $host{location}=tag_expand($infof[2]) if($infof[2]);
  $host{info}=tag_expand($infof[3]) if($infof[3]);

  $id=add_host(\%host);
  fatal("cannot insert host_record! $id") unless ($id > 0);
  $add_count++; 
  $i++;

} while (++$range);



db_ignore_begin_and_commit(0);

print "$add_count host(s) added.\n" if ($opt_verbose);

if ($opt_commit) {
  fatal("cannot commit changes to database") if (db_commit() < 0);
} else {
  db_rollback();
  print "NO CHANGES MADE!\n";
}

exit;


# eof :-)

