#!/usr/bin/perl -Tw
#
# LMS version 1.3.1 Maybourne
#
#  (C) 2001-2004 LMS Developers
#
#  Please, see the doc/AUTHORS for more information about authors!
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License Version 2 as
#  published by the Free Software Foundation.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
#  USA.
#
#  $Id: lms-etherdesc,v 1.5 2004/02/18 12:49:21 lukasz Exp $

use strict;
use DBI;
use Config::IniFiles;
use Getopt::Long;
use vars qw($configfile $quiet $help $version);

my $_version = '1.3.1 Maybourne';

my %options = (
	"--config-file|C=s"	=>	\$configfile,
	"--quiet|q"		=>	\$quiet,
	"--help|h"		=>	\$help,
	"--version|v"		=>	\$version
);

Getopt::Long::config("no_ignore_case");
GetOptions(%options);

if($help)
{
	print STDERR <<EOF;
lms-makearp, version $_version
(C) 2001-2004 LMS Developers

-C, --config-file=/etc/lms/lms.ini	alternate config file (default: /etc/lms/lms.ini);
-h, --help			print this help and exit;
-v, --version			print version info and exit;
-q, --quiet			suppress any output, except errors;

EOF
	exit 0;
}

if($version)
{
	print STDERR <<EOF;
lms-etherdesc, version $_version
(C) 2001-2004 LMS Developers
EOF
	exit 0;
}

if(!$configfile)
{
	$configfile = "/etc/lms/lms.ini";
}

if(!$quiet)
{
	print STDOUT "lms-etherdesc, version $_version\n";
	print STDOUT "(C) 2001-2004 LMS Developers\n";
	print STDOUT "Using file $configfile as config.\n";
}

if(! -r $configfile)
{
	print STDERR "Fatal error: Unable to read configuration file $configfile, exiting.\n";
	exit 1;
}

my $ini = new Config::IniFiles -file => $configfile;

my $networks_list = $ini->val('ether', 'networks') || '';
my $cfile = $ini->val('ether', 'etherdesc_file') || '/var/lib/iptraf/ethernet.desc';
my $cuid = $ini->val('ether', 'etherdesc_owneruid') || '0';
my $cgid = $ini->val('ether', 'etherdesc_ownergid') || '0';
my $cperm = $ini->val('ether', 'etherdesc_permission') || '600';

my $dbtype = $ini->val('database', 'type') || 'mysql';
my $dbhost = $ini->val('database', 'host') || 'localhost';
my $dbuser = $ini->val('database', 'user') || 'root';
my $dbpasswd = $ini->val('database', 'password') || '';
my $dbname = $ini->val('database', 'database') || 'lms';

my $dbase;

if($dbtype eq "mysql")
{
	$dbase = DBI->connect("DBI:mysql:database=$dbname;host=$dbhost","$dbuser","$dbpasswd", { RaiseError => 1 });
}
elsif($dbtype eq "postgres")
{
	$dbase = DBI->connect("DBI:Pg:dbname=$dbname;host=$dbhost","$dbuser","$dbpasswd", { RaiseError => 1 });
}
else
{
	print STDERR "Fatal error: unsupported database type: $dbtype, exiting.\n";
	exit 1;
}

sub mask2prefix($)
{
	my $mask = shift @_;
	my @tmp = split('\.',$mask,4);
	my $q = sprintf("%b%b%b%b",$tmp[0],$tmp[1],$tmp[2],$tmp[3]);
	$q =~ s/0*$//;
	if ($q =~ /0/) {
		print " You idiot. error in mask\n";
	}
	my $len = length($q) ;
	return $len;
}

open(ETHERSFILE, ">$cfile") or die("Fatal error: Unable to write $cfile, exiting.\n");

my $allnetworks = "";

my $dbq = $dbase->prepare("SELECT name FROM networks");
$dbq->execute();
while (my $row = $dbq->fetchrow_hashref()) {
	$allnetworks = "$allnetworks $row->{'name'}";
}

if(!$networks_list) {
	$networks_list = $allnetworks;
}

my @networks = split ' ',$networks_list;

$dbq = $dbase->prepare("SELECT name, mac, ipaddr FROM nodes");
$dbq->execute();
my %maclist;
my %namelist;

while (my $row = $dbq->fetchrow_hashref()) {
	$maclist{$row->{'ipaddr'}} = $row->{'mac'};
	$namelist{$row->{'ipaddr'}} = $row->{'name'};
}

foreach my $key (@networks)
{
	my $dbq = $dbase->prepare("SELECT address, mask FROM networks WHERE name = UPPER('$key')");
	$dbq->execute();
	while (my $row = $dbq->fetchrow_hashref()) 
	{
		my $longip = $row->{'address'};
		my $netsize = 2**(32 - mask2prefix($row->{'mask'}));
		for(my $i=$longip;$i<$longip+$netsize;$i++)
		{
			if($maclist{$i})
			{
	
			my $mac  = lc($maclist{$i});
				my $name = lc($namelist{$i});
			
				$mac =~ s/://g;

				print ETHERSFILE "$mac:$name\n";
			}
		}
	}
}

$dbase->disconnect();
close(ETHERSFILE);
chown $cuid, $cgid, $cfile or print "Warning! Unable to set owner of $cfile to $cuid.$cgid.\n";
chmod oct($cperm), $cfile or print "Warning! Unable to set permission $cperm to $cfile.\n";
