Hello  Marcel,

> does ClamAV provide SNMP support? My idea is that ClamAV sends snmp
> traps with all information (like the results at the prompt) to a snmp
> server like OpenNMS, when a virus was found. OpenNMS is a network
> management system. Primary it monitors network infrastructures. But
> you can also handle snmp traps from printers, servers, programs and
> and and... 
> So why not from ClamAV?

You're talking about the command line (prompt) so I guess you are not scanning 
emails but 
rather directories... but, who knows, this might give you ideas.

I use ClamAV for mail scanning and I don't send traps on mail viruses and spams 
as there 
are too many of them, but I let my management system query the mail relay via 
SNMP every 
5 minutes.

I added this to my snmpd.conf:
exec 1.3.6.1.4.1.2021.8.990 mailstat.pl /usr/sbin/mailstat.pl -t
exec 1.3.6.1.4.1.2021.8.991 mailstat.pl /usr/sbin/mailstat.pl -v

And I created the mailstat.pl as follows. Of course, depending on your needs 
and on the tools 
you use, you might have to tune this... It computes statistics out of 
/var/log/syslog and out of 
the output of /usr/bin/mailstats (that you might need to initialize first, and 
reset at midnight for 
instance). Persistent counters are saved in /var/log/mailstats.

--mailstat.pl---------------------------
#!/usr/bin/perl
# Dhn, 2008/06/30
# Script used by snmpd to collect and return mail statistics but
#   it can run from the CLI too.
# Usage: mailstat.pl [-t] [-v]
#   Returns the "title:value" statistics by defaults, or only the titles (-t)
#   or only the values (-v). The statistics are always displayed in the 
#   same order (see @keys array).
#use strict;

# Defaults
my $in="/var/log/syslog";               # log pipe
my $stats="/var/log/mailstats";         # persistent counters
my $fl = "";                            # flags for output (''|t|v)
my %ctr = ();                           # current counters
my $w = 0;                              # write flag
my @ln = ();                            # splitted line
my @arr = ();                           # splitted word
my @stat = ();                          # file stats
my $key = "";                           # one hash key
my $out = "";                           # buffer for outputt
#my $pos = 0;                           # current position
my @keys = qw/accepted blacklisted discard greeting ham mail pca seen spam 
unknown
     virus bytesfr bytesto msgsfr msgsto connfr connto mailq inode position 
zlast/;


# Functions / handlers
sub writestats {
  $ctr{"seen"} = $ctr{"greeting"} + $ctr{"blacklisted"} + $ctr{"unknown"} + 
$ctr{"spam"} +
     + $ctr{"virus"} + $ctr{"ham"};
  $ctr{"accepted"} = $ctr{"spam"} - $ctr{"discard"} + $ctr{"ham"};
  $ctr{"pca"} = int(($ctr{"seen"} != 0) ? (10000 * $ctr{"accepted"} / 
$ctr{"seen"}) : 0)/100;
  #$ctr{"position"} = $pos;
  open OUT, ">", $stats or die "Cannot open $stats for writing: $!\n";
  $out = "";
  #foreach $key (sort keys %ctr) {
  foreach $key (@keys) {
    if ($key eq "zlast") {
      printf OUT "%12s: %-60s\n", $key, $ctr{$key};
    } else {
      printf OUT "%12s: %12d\n", $key, $ctr{$key};
    }
    &saveout($key);
  }
  close OUT;
  $w = 0;
}

sub saveout {
  my $key = @_[0];
  return if ($key eq "inode" || $key eq "position" || $key eq "zlast");
  if ($fl eq "t") {
    $out .= "$key\n";
  } elsif ($fl eq "v") {
    $out .= "$ctr{$key}\n";
  } else {
    $out .= sprintf("%12s: %12d\n", $key, $ctr{$key});
  }
}

sub computestats {
  seek IN, $ctr{"position"}, SEEK_SET;
  #$pos = $ctr{"position"};
  while (<IN>) {
    #$pos += length($_);
    $ctr{"position"} += length($_);
    $ctr{"zlast"} = substr($_, 0, 60);
    @ln = split;
    if (/ sendmail.* reject=550 5.7.1 Spam blocked /) {
      $ctr{"blacklisted"}++; $w++;
    } elsif (/ sendmail.* reject=550 5.1.1 .* User unknown/) {
      $ctr{"unknown"}++; $w++;
    } elsif (/ sendmail.* due to pre-greeting traffic/) {
      $ctr{"greeting"}++; $w++;
    } elsif ($ln[4] =~ /^mimedefang.pl/ && $ln[8] =~ /^MDLOG,/) {
      @arr = split /,/, $ln[8];
      #if ($arr[2] eq "spam" && $arr[3] > 9) {
      #  $ctr{"spam"}++; $ctr{"discard"}++; $w++;
      if ($arr[2] eq "spamd") {
        $ctr{"spam"}++; $ctr{"discard"}++; $w++;
      } elsif ($arr[2] eq "spam") {
        $ctr{"spam"}++; $w++;
      } elsif ($arr[2] eq "virus") {
        if ($arr[3] =~ /^Sanesecurity/) {
          $ctr{"spam"}++; $ctr{"discard"}++; $w++;
        } else {
          $ctr{"virus"}++; $w++;
        }
      } elsif ($arr[2] eq "ham") {
        $ctr{"ham"}++; $w++;
      } elsif ($arr[2] eq "mail_in") {
        $ctr{"mail"}++; $w++;
      }
    }
    &writestats if ($w >= 100);
  }
}

sub sendmailstats {
  open STATS, "/usr/bin/mailstats|" or die "$0: mailstats error 
/usr/bin/mailstats: $!";
  while (chomp ($line = <STATS>)) {
    if ($. > 2) {
      ($m, $line) = split(' ', $line, 2);
      if ($m eq "T") {
        ($msgsfr, $bytesfr, $msgsto, $bytesto) = (split (/ +/, $line))[0,1,2,3];
        chop $bytesfr; # remove "K"
        chop $bytesto;
      } elsif ($m eq "C") {
        ($connfr, $connto, $connrej) = split (/ +/, $line);
      }
    }
  }
  close STATS;
  $ctr{"bytesfr"} = $bytesfr * 1024;
  $ctr{"bytesto"} = $bytesto * 1024;
  $ctr{"msgsfr"} = $msgsfr;
  $ctr{"msgsto"} = $msgsto;
  $ctr{"connfr"} = $connfr;
  $ctr{"connto"} = $connto;
  $mailq = qx:ls /var/spool/mqueue/q* 2>/dev/null | wc -l:;
  $mailq =~ s/\s//g;
  $ctr{"mailq"} = $mailq;
  $w++;
}

sub terminate {
  &writestats if ($w >= 1);
  print $out;
  exit 0;
}

$SIG{"INT"} = \&terminate;
$SIG{"QUIT"} = \&terminate;
$SIG{"TERM"} = \&terminate;
$SIG{"HUP"} = \&writestats;

# Parse arguments
while ($o = shift @ARGV) {
  if ($o eq "-t") {
    $fl = "t";
  } elsif ($o eq "-v") {
    $fl = "v";
  } else {
    print "Usage: $0 [-t|-v]\n";
    print "  Compute mail statistics and display the result (counters).\n";
    print "    -t display only titles, -v display only values\n";
    exit 1;
  }
}

# Read current counters
open IN, $stats or die "Cannot open $stats for reading: $!\n";
while (chomp($_ = <IN>)) {
  /^ *(\S+): +(.+)$/;
  $ctr{$1} = $2;
  &saveout($1);
}
close IN;
&sendmailstats;

# Compute new totals
open IN, $in or die "Cannot open $in for reading: $!\n";
@stat = stat IN;
$ctr{"inode"} = @stat[1] unless (defined $ctr{"inode"});
$ctr{"position"} = 0 unless (defined $ctr{"position"});
if ($stat[1] != $ctr{"inode"}) {
  close IN;
  open IN, "$in.0" or die "Cannot open $in.0 for reading: $!\n";
  &computestats;
  close IN;
  open IN, $in or die "Cannot open $in for reading: $!\n";
  $ctr{"inode"} = @stat[1];
  $ctr{"position"} = 0;
  #$pos = 0;
  &writestats;
}
&computestats;
close IN;
&terminate;

# End of script
-----------------------------------
I give no guarantee on this script... and I don't say it is the best ever 
written but it works well 
here.

HTH,
Pierre
_______________________________________________
Help us build a comprehensive ClamAV guide: visit http://wiki.clamav.net
http://www.clamav.net/support/ml

Reply via email to