#!/usr/bin/perl
#
# ulogd2specter
#   simple script to convert ulogd 1.02/1.10 config files
#   into specter's >= 1.1
#
# (C) 2004 by Michal Kwiatkowski <ruby@joker.linuxstuff.pl>
# 
# This code is released under the terms of GNU GPL.
#
# Last updated: 18 Jul 2004
#
# Note:
#   It won't work if you have non-standard plugin names,
#   not in form ulogd_PLUGINNAME.so
#
#   Since things in config got moved around, script don't
#   preserve comments.
#

use strict; # I'm a C programmer, sorry ;)

my $output;


if (!defined($ARGV[0])) {
	print "usage:  ulogd2specter.pl [input file] [output file]\n";
	exit;
}

if (!defined($ARGV[1])) {
	$output = '-';
}
else {
	$output = $ARGV[1];
}


# ------- read file, omitting comments and empty lines

my ($fd, $content);

open($fd, $ARGV[0]) || die "Can't open $ARGV[0]: $!\n";
while (<$fd>) {
	if ($_ !~ /\A[ \t]*#.*/ && $_ =~ /\A([\w\t =\[\]\"\/\.]+)#*/) {
		$content .= $1."\n";
	}
}
close($fd);


# ------- decide which version input file is (1.02 or 1.10)

my ($sep, $version);

if ($content =~ /\[\w+\]/) {
	$version = "1.10";
	$sep = "[\t =]+";
}
else {
	$version = "1.02";
	$sep = "[\t ]+";
}

print "Detected ulogd $version config.\n";


# ------- check which plugins are present

my %plugins;
while ($content =~ /plugin$sep"?([\w\/\.]+)ulogd_([A-Za-z]+)\.so/g) {
	$plugins{$2} = $1;
}

foreach (keys %plugins) {
	if ($version eq "1.10" && $_ =~ "SYSLOG") {
		next;
	}
	if ($_ !~ "BASE|LOCAL|LOGEMU|OPRINT|PWSNIFF|MYSQL|PGSQL|PCAP") {
		print STDERR "Warning: Plugin $_ not known, omiting.\n";
	}
}

# ------- open output file and insert some head notes

open($fd, '>'.$output) || die "Can't open $output: $!\n";

print $fd <<EOF
#
# configuration file for specter
#     generated by ulogd2specter.pl
#
# Each execution group (the same you specify with iptables options
# --ulog-nlgroup or --set-mark, depending on grouping method chosen)
# has its separate block, enclosed within curly brackets, so you can
# specify different options for different groups independently.
#
# Refer to specter.conf(5) manual for more information.
#
EOF
;


# ------- parse global options

print $fd "\nglobal {\n";
if ($content =~ /loglevel$sep(("?)\d+\2)/) { print $fd "\tloglevel $1\n" }
if ($content =~ /logfile$sep(("?)[ \w\/\.]+\2)/) { print $fd "\tlogfile $1\n" }
if ($content =~ /rmem$sep(("?)\d+\2)/) { print $fd "\trmem $1\n" }
if ($content =~ /bufsize$sep(("?)\d+\2)/) { print $fd "\tbufsize $1\n" }
print $fd "}\n";


# ------- parse plugins paths

print $fd "\nplugins {\n";
if (defined($plugins{BASE})) {
	print $fd "\tBASE\t$plugins{BASE}specter/specter_BASE.so\n";
}
if (defined($plugins{LOCAL})) {
	print $fd "\tLOCAL\t$plugins{LOCAL}specter/specter_LOCAL.so\n";
}
elsif (defined($plugins{LOGEMU})) {
	print $fd "\tLOCAL\t$plugins{LOGEMU}specter/specter_LOCAL.so\n";
	if (! -e "$plugins{LOGEMU}specter/specter_LOCAL.so"
	&& ! -e "$plugins{LOGEMU}ulogd/ulogd_LOCAL.so") {
		print STDERR "Warning: specter_LOCAL.so needed by LOGEMU plugin.\n",
		"         Guessing it should be in $plugins{LOGEMU}specter/\n";
	}
}
if (defined($plugins{LOGEMU})) {
	print $fd "\tLOGEMU\t$plugins{LOGEMU}specter/specter_LOGEMU.so\n";
}
if (defined($plugins{OPRINT})) {
	print $fd "\tOPRINT\t$plugins{OPRINT}specter/specter_OPRINT.so\n";
}
if (defined($plugins{PWSNIFF})) {
	print $fd "\tPWSNIFF\t$plugins{PWSNIFF}specter/specter_PWSNIFF.so\n";
}
if (defined($plugins{MYSQL})) {
	print $fd "\tMYSQL\t$plugins{MYSQL}specter/specter_MYSQL.so\n";
}
if (defined($plugins{PGSQL})) {
	print $fd "\tPGSQL\t$plugins{PGSQL}specter/specter_PGSQL.so\n";
}
if (defined($plugins{PCAP})) {
	print $fd "\tPCAP\t$plugins{PCAP}specter/specter_PCAP.so\n";
}
print $fd "}\n";


# ------- parse execution group

if ($content =~ /nlgroup$sep(("?)\d+\2)/) { print $fd "\n$1 {\n" } else { print $fd "\n1 {\n" }
if (defined($plugins{BASE})) {
	print $fd "\t:BASE\n";
}
if (defined($plugins{LOCAL}) || defined($plugins{LOGEMU})) {
	print $fd "\t:LOCAL\n";
}
if (defined($plugins{PWSNIFF})) {
	print $fd "\t:PWSNIFF\n";
}
if (defined($plugins{LOGEMU})) {
	print $fd "\t:LOGEMU\n";
	if ($version eq "1.02") {
		if ($content =~ /syslogfile$sep(("?)[\w\/\.]+\2)/) { print $fd "\tlogfile $1\n" }
		if ($content =~ /syslogsync$sep("?)(\d+)\1/) { if ($2) { print $fd "\tsync\n" } }
	}
	elsif ($version eq "1.10" && $content =~ /\[LOGEMU\]([^\[]*)(\[|\z)/) {
		$_ = $1;
		if (/file$sep(("?)[\w\/\.]+\2)/) { print $fd "\tlogfile $1\n" }
		if (/sync$sep("?)(\d+)\1/) { if ($2) { print $fd "\tsync\n" } }
	}
	print $fd "\n";
}
if (defined($plugins{OPRINT})) {
	print $fd "\t:OPRINT\n";
	if ($version eq "1.02") {
		if ($content =~ /dumpfile$sep(("?)[\w\/\.]+\2)/) { print $fd "\tlogfile $1\n" }
	}
	elsif ($version eq "1.10" && $content =~ /\[OPRINT\]([^\[]*)(\[|\z)/) {
		$_ = $1;
		if (/file$sep(("?)[\w\/\.]+\2)/) { print $fd "\tlogfile $1\n" }
	}
	print $fd "\n";
}
if (defined($plugins{MYSQL})) {
	print $fd "\t:MYSQL\n";
	if ($version eq "1.02") {
		if ($content =~ /mysqltable$sep(("?)[\w\/\.]+\2)/) { print $fd "\ttable $1\n" }
		if ($content =~ /mysqlpass$sep(("?)[\w\/\.]+\2)/) { print $fd "\tpass $1\n" }
		if ($content =~ /mysqluser$sep(("?)[\w\/\.]+\2)/) { print $fd "\tuser $1\n" }
		if ($content =~ /mysqldb$sep(("?)[\w\/\.]+\2)/) { print $fd "\tdb $1\n" }
		if ($content =~ /mysqlhost$sep(("?)[\w\/\.]+\2)/) { print $fd "\thost $1\n" }
	}
	elsif ($version eq "1.10" && $content =~ /\[MYSQL\]([^\[]*)(\[|\z)/) {
		$_ = $1;
		if (/table$sep(("?)[\w\/\.]+\2)/) { print $fd "\ttable $1\n" }
		if (/pass$sep(("?)[\w\/\.]+\2)/) { print $fd "\tpass $1\n" }
		if (/user$sep(("?)[\w\/\.]+\2)/) { print $fd "\tuser $1\n" }
		if (/db$sep(("?)[\w\/\.]+\2)/) { print $fd "\tdb $1\n" }
		if (/host$sep(("?)[\w\/\.]+\2)/) { print $fd "\thost $1\n" }
	}
	print $fd "\n";
}
if (defined($plugins{PGSQL})) {
	print $fd "\t:PGSQL\n";
	if ($version eq "1.02") {
		if ($content =~ /pgsqltable$sep(("?)[\w\/\.]+\2)/) { print $fd "\ttable $1\n" }
		if ($content =~ /pgsqlpass$sep(("?)[\w\/\.]+\2)/) { print $fd "\tpass $1\n" }
		if ($content =~ /pgsqluser$sep(("?)[\w\/\.]+\2)/) { print $fd "\tuser $1\n" }
		if ($content =~ /pgsqldb$sep(("?)[\w\/\.]+\2)/) { print $fd "\tdb $1\n" }
		if ($content =~ /pgsqlhost$sep(("?)[\w\/\.]+\2)/) { print $fd "\thost $1\n" }
	}
	elsif ($version eq "1.10" && $content =~ /\[PGSQL\]([^\[]*)(\[|\z)/) {
		$_ = $1;
		if (/table$sep(("?)[\w\/\.]+\2)/) { print $fd "\ttable $1\n" }
		if (/pass$sep(("?)[\w\/\.]+\2)/) { print $fd "\tpass $1\n" }
		if (/user$sep(("?)[\w\/\.]+\2)/) { print $fd "\tuser $1\n" }
		if (/db$sep(("?)[\w\/\.]+\2)/) { print $fd "\tdb $1\n" }
		if (/host$sep(("?)[\w\/\.]+\2)/) { print $fd "\thost $1\n" }
	}
	print $fd "\n";
}
if (defined($plugins{PCAP})) {
	print $fd "\t:PCAP\n";
	if ($version eq "1.02") {
		if ($content =~ /pcapfile$sep(("?)[\w\/\.]+\2)/) { print $fd "\tlogfile $1\n" }
		if ($content =~ /pcapsync$sep("?)(\d+)\1/) { if ($2) { print $fd "\tsync\n" } }
	}
	elsif ($version eq "1.10" && $content =~ /\[PCAP\]([^\[]*)(\[|\z)/) {
		$_ = $1;
		if (/file$sep(("?)[\w\/\.]+\2)/) { print $fd "\tlogfile $1\n" }
		if (/sync$sep("?)(\d+)\1/) { if ($2) { print $fd "\tsync\n" } }
	}
	print $fd "\n";
}
print $fd "}\n";


# ------- we're done

close $fd;

