#!/usr/bin/perl -I/usr/local/sauron
#
# export-vmps  generates VMPS configuration file (from given server)
#
# Copyright (c) Timo Kokkonen <tjko@iki.fi>  2003.
# $Id: export-vmps,v 1.5 2003/12/28 19:29:12 tjko Exp $
#
require 5;
use Getopt::Long;
use Time::Local;
use Sauron::DB;
use Sauron::Util;
use Sauron::BackEnd;
use Sauron::Sauron;

load_config();

$user = (getpwuid($<))[0];
$host = `hostname`;
$host =~ s/\n//g;
$time_now = localtime;
$tnow = time();
$tmp_extension = ".tmp.$<.$$"; # generate extension for temp files

GetOptions("help|h","verbose|v","all|a","comments|c");

if ($opt_help || @ARGV < 3) {
  print "syntax: $0 [--help] [OPTIONS] <servername> <vmpsdomain> <filename>\n",
        "\noptions:\n",
	"\t--all\t\tinclude ALL hosts from this server\n",
	"\t--comments\tinclude comments into output file\n",
	"\t--verbose\tmore verbose output\n";
  print "\n" if ($opt_help);
  exit(0);
}

$opt_comments = ($opt_comments ? 1 : 0);
$opt_verbose = ($opt_verbose ? 1 : 0);
$opt_all = ($opt_all ? 1 : 0);
$servername=shift;
$vmpsname=shift;
$filename=shift;

db_connect();

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

$vmpsid=get_vmps_by_name($serverid,$vmpsname);
fatal("cannot find VMPS Domain '$vmpsname'") unless ($vmpsid > 0);

fatal("cannot get VMPS record!") if (get_vmps($vmpsid,\%vmps) < 0);

if ($vmps{fallback} > 0) {
  db_query("SELECT name FROM vlans WHERE id=$vmps{fallback}",\@q);
  fatal("cannot get vlan name (id=$vmps{fallback})") unless ($q[0][0]);
  $fallback = $q[0][0];
} elsif ($vmps{fallback} == -1) {
  $fallback = 'none';
} elsif ($vmps{fallback} == -2) {
  $fallback = 'default';
} else {
  fatal("invalid value in fallback field ($vmps{fallback})");
}

fatal("target file is a directory") if (-d $filename);
$tmpfilename=$filename.$tmp_extension;

print "opening file: $tmpfilename\n" if ($opt_verbose);
open(FILE,">$tmpfilename") ||
  fatal("cannot open temporary file: $tmpfilename");

# let's generate the configuration file

print FILE "!VMPS File Format, version 1.1\n!\n",
           "! VMPS config -- automagically generated by Sauron " .
           sauron_version()."\n",
           "!                created by $user\@$host at $time_now\n!\n!\n";

print FILE "! VMPS domain\n",
      "vmps domain $vmpsname\n!\n",
      "vmps mode ".($vmps{mode}==0?'open':'secure')."\n!\n",
      "vmps no-domain-req ".($vmps{nodomainreq}==0?'allow':'deny')."\n!\n",
      "! VLAN to use if MAC not known\n",
      ($vmps{fallback}==-1 ? '! ':'')."vmps fallback $fallback\n!\n!\n",
      "! MAC Addresses\n!\n",
      "! address <addr> vlan-name <vlan-name>\n!\n",
      "vmps-mac-addrs\n\n";


db_query("SELECT h.id,h.domain,h.ether,v.name,a.ip,h.expiration " .
	 "FROM zones z JOIN hosts h ON h.zone=z.id " .
         " JOIN a_entries a ON a.host=h.id JOIN nets n ON a.ip << n.net " .
         " JOIN vlans v ON n.vlan=v.id LEFT JOIN groups g ON h.grp=g.id " .
         " LEFT JOIN vmps w ON g.vmps=w.id " .
	 "WHERE z.server=$serverid AND h.type=1 AND h.ether != '' " .
	  ($opt_all ? "" : " AND w.id=$vmpsid ") .
         "ORDER BY a.ip,n.net",\@q);

print "Found ".@q." results in database\n" if ($opt_verbose);


for $i (0..$#q) {
  ($id,$domain,$ether,$vlan,$ip,$edate) = @{$q[$i]};
  next if ($q[$i+1][0] == $id);
  if ($edate > 0 && $edate < $tnow) {
    print "skipping expired host: $domain,$ether,$vlan\n" if ($opt_verbose);
    next;
  }

  print FILE "! $domain ($ip)\n" if ($opt_comments);
  $ether=lc($ether);
  unless ($ether =~ /^([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})$/) {
    error("invalid ethernet address: $host ($ether)");
    next;
  }

  print FILE "address $1.$2.$3 vlan-name $vlan\n";

}

print FILE "!\n! eof\n";
close(FILE);

print "rename: $tmpfilename --> $filename\n" if ($opt_verbose);
fatal("failed to rename temp file!") unless (rename($tmpfilename,$filename));

exit 0;

# eof

