From 218e31fad735e9710ecc63c852748ba4d317208c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Sun, 24 Sep 2023 14:18:21 +0200 Subject: d/changelog: Change distribution to unstable, Change date and time --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index c1b2631..6cb63cc 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -mailgraph (1.14-21) UNRELEASED; urgency=medium +mailgraph (1.14-21) unstable; urgency=medium * New debian/patches/0100-new_syslog_format.patch: - support the new syslog format (Closes: #1051496) @@ -10,7 +10,7 @@ mailgraph (1.14-21) UNRELEASED; urgency=medium * debian/mailgraph.conf: - Move directory to /usr/lib/cgi-bin. - -- Jörg Frings-Fürst Sat, 23 Sep 2023 12:24:48 +0200 + -- Jörg Frings-Fürst Sun, 24 Sep 2023 14:12:17 +0200 mailgraph (1.14-20) unstable; urgency=medium -- cgit v1.2.3 From 6b6036901e61647173e4ac8af83ac8bb85a51c16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Sun, 24 Sep 2023 16:17:08 +0200 Subject: fix typo --- debian/patches/0100-new_syslog_format.patch | 2 +- debian/patches/0100-new_syslog_format.patch~ | 1239 ++++++++++++++++++++++++++ 2 files changed, 1240 insertions(+), 1 deletion(-) create mode 100644 debian/patches/0100-new_syslog_format.patch~ diff --git a/debian/patches/0100-new_syslog_format.patch b/debian/patches/0100-new_syslog_format.patch index 5344f07..f3fc9a0 100644 --- a/debian/patches/0100-new_syslog_format.patch +++ b/debian/patches/0100-new_syslog_format.patch @@ -71,7 +71,7 @@ Index: trunk/mailgraph.pl + $self->{year}=$year; + } + else { -+ my($montxt, $mon); ++ my($montxt); + ($montxt, $day, $hour, $min, $sec, $host, $text) = $str =~ /^ + (\S{3})\s+(\d+) # date + \s diff --git a/debian/patches/0100-new_syslog_format.patch~ b/debian/patches/0100-new_syslog_format.patch~ new file mode 100644 index 0000000..5344f07 --- /dev/null +++ b/debian/patches/0100-new_syslog_format.patch~ @@ -0,0 +1,1239 @@ +Description: Add new syslog format +Author: M.D. Klapwijk +Origin: https://gist.github.com/mdklapwijk/4f8d2fc39f09f4aa615cbf8ffae0379a +Bug: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1051496 +Forwarded: not-needed +Last-Update: 2023-09-23 +--- +This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ +Index: trunk/mailgraph.pl +=================================================================== +--- trunk.orig/mailgraph.pl ++++ trunk/mailgraph.pl +@@ -5,6 +5,10 @@ + # copyright (c) 2000-2007 David Schweikert + # released under the GNU General Public License + ++# modifications to handle rsyslog high precision format ++# copyright (c) 2018 by M.D. Klapwijk ++# released under the GNU General Public License ++ + ######## Parse::Syslog 1.09 (automatically embedded) ######## + package Parse::Syslog; + use Carp; +@@ -85,7 +89,7 @@ sub str2time($$$$$$$$) + # - compensate if yes + # note that we assume that the DST-switch goes like this: + # time 1:00 1:30 2:00 2:30 2:00 2:30 3:00 3:30 +- # stamp 1 2 3 4 3 3 7 8 ++ # stamp 1 2 3 4 3 3 7 8 + # comp. 0 0 0 0 2 2 0 0 + # result 1 2 3 4 5 6 7 8 + # old Time::Local versions behave differently (1 2 5 6 5 6 7 8) +@@ -202,27 +206,46 @@ sub _next_syslog($) + } + my $file = $self->{file}; + line: while(defined (my $str = $self->_next_line)) { +- # date, time and host +- $str =~ /^ +- (\S{3})\s+(\d+) # date -- 1, 2 +- \s +- (\d+):(\d+):(\d+) # time -- 3, 4, 5 +- (?:\s<\w+\.\w+>)? # FreeBSD's verbose-mode +- \s +- ([-\w\.\@:]+) # host -- 6 +- \s+ +- (?:\[LOG_[A-Z]+\]\s+)? # FreeBSD +- (.*) # text -- 7 +- $/x or do +- { +- warn "WARNING: line not in syslog format: $str"; +- next line; +- }; +- my $mon = $months_map{$1}; +- defined $mon or croak "unknown month $1\n"; +- $self->_year_increment($mon); ++ # date, time and host ++ my ($year, $mon, $day, $hour, $min, $sec, $host, $text); ++ if($self->{type} eq 'rsyslog') { ++ ($year, $mon, $day, $hour, $min, $sec, $host, $text) = $str =~ /^ ++ (\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)\S+ # datetime ++ \s+ ++ (\S+) # host ++ \s+ ++ (.*) # text ++ $/x or do ++ { ++ warn "WARNING: line not in high precision rsyslog format: $str"; ++ next line; ++ }; ++ $mon--; ++ $self->{year}=$year; ++ } ++ else { ++ my($montxt, $mon); ++ ($montxt, $day, $hour, $min, $sec, $host, $text) = $str =~ /^ ++ (\S{3})\s+(\d+) # date ++ \s ++ (\d+):(\d+):(\d+) # time ++ (?:\s<\w+\.\w+>)? # FreeBSD's verbose-mode ++ \s ++ ([-\w\.\@:]+) # host ++ \s+ ++ (?:\[LOG_[A-Z]+\]\s+)? # FreeBSD ++ (.*) # text ++ $/x or do ++ { ++ warn "WARNING: line not in syslog format: $str"; ++ next line; ++ }; ++ $mon = $months_map{$montxt}; ++ defined $mon or croak "unknown month $montxt\n"; ++ $self->_year_increment($mon); ++ } + # convert to unix time +- my $time = $self->str2time($5,$4,$3,$2,$mon,$self->{year}-1900,$self->{GMT}); ++ my $time = $self->str2time($sec,$min,$hour,$day,$mon,$self->{year}-1900,$self->{GMT}); + if(not $self->{allow_future}) { + # accept maximum one day in the present future + if($time - time > 86400) { +@@ -230,7 +253,6 @@ sub _next_syslog($) + next line; + } + } +- my ($host, $text) = ($6, $7); + # last message repeated ... times + if($text =~ /^(?:last message repeated|above message repeats) (\d+) time/) { + next line if defined $self->{repeat} and not $self->{repeat}; +@@ -264,11 +286,11 @@ sub _next_syslog($) + }; + if($self->{arrayref}) { + $self->{_last_data}{$host} = [ +- $time, # 0: timestamp +- $host, # 1: host +- $1, # 2: program +- $2, # 3: pid +- $6, # 4: text ++ $time, # 0: timestamp ++ $host, # 1: host ++ $1, # 2: program ++ $2, # 3: pid ++ $6, # 4: text + ]; + } + else { +@@ -292,12 +314,12 @@ sub _next_metalog($) + my ($self) = @_; + my $file = $self->{file}; + line: while(my $str = $self->_next_line) { +- # date, time and host +- $str =~ /^ ++ # date, time and host ++ $str =~ /^ + (\S{3})\s+(\d+) # date -- 1, 2 + \s + (\d+):(\d+):(\d+) # time -- 3, 4, 5 +- # host is not logged ++ # host is not logged + \s+ + (.*) # text -- 6 + $/x or do +@@ -310,22 +332,22 @@ sub _next_metalog($) + $self->_year_increment($mon); + # convert to unix time + my $time = $self->str2time($5,$4,$3,$2,$mon,$self->{year}-1900,$self->{GMT}); +- my $text = $6; ++ my $text = $6; + $text =~ /^ + \[(.*?)\] # program -- 1 +- # no PID +- \s+ ++ # no PID ++ \s+ + (.*) # text -- 2 + $/x or do + { +- warn "WARNING: text line not in metalog format: $text ($str)"; ++ warn "WARNING: text line not in metalog format: $text ($str)"; + next line; + }; + if($self->{arrayref}) { + return [ +- $time, # 0: timestamp +- 'localhost', # 1: host +- $1, # 2: program ++ $time, # 0: timestamp ++ 'localhost', # 1: host ++ $1, # 2: program + undef, # 3: (no) pid + $2, # 4: text + ]; +@@ -344,7 +366,7 @@ sub _next_metalog($) + sub next($) + { + my ($self) = @_; +- if($self->{type} eq 'syslog') { ++ if($self->{type} eq 'syslog' || $self->{type} eq 'rsyslog') { + return $self->_next_syslog(); + } + elsif($self->{type} eq 'metalog') { +@@ -373,15 +395,16 @@ my $points_per_sample = 3; + + my $daemon_logfile = '/var/log/mailgraph.log'; + my $daemon_pidfile = '/var/run/mailgraph.pid'; +-my $daemon_rrd_dir = '/var/log'; ++my $daemon_rrd_dir = '/var/lib/mailgraph'; + + # global variables + my $logfile; + my $rrd = "mailgraph.rrd"; + my $rrd_virus = "mailgraph_virus.rrd"; ++my $rrd_greylist = "mailgraph_greylist.rrd"; + my $year; + my $this_minute; +-my %sum = ( sent => 0, received => 0, bounced => 0, rejected => 0, virus => 0, spam => 0 ); ++my %sum = ( sent => 0, received => 0, bounced => 0, rejected => 0, virus => 0, spam => 0, greylisted => 0, delayed => 0); + my $rrd_inited=0; + + my %opt = (); +@@ -395,499 +418,550 @@ sub event_bounced($); + sub event_rejected($); + sub event_virus($); + sub event_spam($); ++sub event_greylisted($); ++sub event_delayed($); + sub init_rrd($); + sub update($); + + sub usage + { +- print "usage: mailgraph [*options*]\n\n"; +- print " -h, --help display this help and exit\n"; +- print " -v, --verbose be verbose about what you do\n"; +- print " -V, --version output version information and exit\n"; +- print " -c, --cat causes the logfile to be only read and not monitored\n"; +- print " -l, --logfile f monitor logfile f instead of /var/log/syslog\n"; +- print " -t, --logtype t set logfile's type (default: syslog)\n"; +- print " -y, --year starting year of the log file (default: current year)\n"; +- print " --host=HOST use only entries for HOST (regexp) in syslog\n"; +- print " -d, --daemon start in the background\n"; +- print " --daemon-pid=FILE write PID to FILE instead of /var/run/mailgraph.pid\n"; +- print " --daemon-rrd=DIR write RRDs to DIR instead of /var/log\n"; +- print " --daemon-log=FILE write verbose-log to FILE instead of /var/log/mailgraph.log\n"; +- print " --ignore-localhost ignore mail to/from localhost (used for virus scanner)\n"; +- print " --ignore-host=HOST ignore mail to/from HOST regexp (used for virus scanner)\n"; +- print " --only-mail-rrd update only the mail rrd\n"; +- print " --only-virus-rrd update only the virus rrd\n"; +- print " --rrd-name=NAME use NAME.rrd and NAME_virus.rrd for the rrd files\n"; +- print " --rbl-is-spam count rbl rejects as spam\n"; +- print " --virbl-is-virus count virbl rejects as viruses\n"; ++ print "usage: mailgraph [*options*]\n\n"; ++ print " -h, --help display this help and exit\n"; ++ print " -v, --verbose be verbose about what you do\n"; ++ print " -V, --version output version information and exit\n"; ++ print " -c, --cat causes the logfile to be only read and not monitored\n"; ++ print " -l, --logfile f monitor logfile f instead of /var/log/syslog\n"; ++ print " -t, --logtype t set logfile's type (default: syslog)\n"; ++ print " -y, --year starting year of the log file (default: current year)\n"; ++ print " --host=HOST use only entries for HOST (regexp) in syslog\n"; ++ print " -d, --daemon start in the background\n"; ++ print " --daemon-pid=FILE write PID to FILE instead of /var/run/mailgraph.pid\n"; ++ print " --daemon-rrd=DIR write RRDs to DIR instead of /var/lib/mailgraph\n"; ++ print " --daemon-log=FILE write verbose-log to FILE instead of /var/log/mailgraph.log\n"; ++ print " --ignore-localhost ignore mail to/from localhost (used for virus scanner)\n"; ++ print " --ignore-host=HOST ignore mail to/from HOST regexp (used for virus scanner)\n"; ++ print " --no-mail-rrd no update mail rrd\n"; ++ print " --no-virus-rrd no update virus rrd\n"; ++ print " --no-greylist-rrd no update greylist rrd\n"; ++ print " --rrd-name=NAME use NAME.rrd and NAME_virus.rrd for the rrd files\n"; ++ print " --rbl-is-spam count rbl rejects as spam\n"; ++ print " --virbl-is-virus count virbl rejects as viruses\n"; + +- exit; ++ exit; + } + + sub main + { +- Getopt::Long::Configure('no_ignore_case'); +- GetOptions(\%opt, 'help|h', 'cat|c', 'logfile|l=s', 'logtype|t=s', 'version|V', +- 'year|y=i', 'host=s', 'verbose|v', 'daemon|d!', +- 'daemon_pid|daemon-pid=s', 'daemon_rrd|daemon-rrd=s', +- 'daemon_log|daemon-log=s', 'ignore-localhost!', 'ignore-host=s@', +- 'only-mail-rrd', 'only-virus-rrd', 'rrd_name|rrd-name=s', +- 'rbl-is-spam', 'virbl-is-virus' +- ) or exit(1); +- usage if $opt{help}; +- +- if($opt{version}) { +- print "mailgraph $VERSION by david\@schweikert.ch\n"; +- exit; +- } +- +- $daemon_pidfile = $opt{daemon_pid} if defined $opt{daemon_pid}; +- $daemon_logfile = $opt{daemon_log} if defined $opt{daemon_log}; +- $daemon_rrd_dir = $opt{daemon_rrd} if defined $opt{daemon_rrd}; +- $rrd = $opt{rrd_name}.".rrd" if defined $opt{rrd_name}; +- $rrd_virus = $opt{rrd_name}."_virus.rrd" if defined $opt{rrd_name}; +- +- # compile --ignore-host regexps +- if(defined $opt{'ignore-host'}) { +- for my $ih (@{$opt{'ignore-host'}}) { +- push @{$opt{'ignore-host-re'}}, qr{\brelay=[^\s,]*$ih}i; +- } +- } +- +- if($opt{daemon} or $opt{daemon_rrd}) { +- chdir $daemon_rrd_dir or die "mailgraph: can't chdir to $daemon_rrd_dir: $!"; +- -w $daemon_rrd_dir or die "mailgraph: can't write to $daemon_rrd_dir\n"; +- } +- +- daemonize if $opt{daemon}; +- +- my $logfile = defined $opt{logfile} ? $opt{logfile} : '/var/log/syslog'; +- my $file; +- if($opt{cat}) { +- $file = $logfile; +- } +- else { +- $file = File::Tail->new(name=>$logfile, tail=>-1); +- } +- my $parser = new Parse::Syslog($file, year => $opt{year}, arrayref => 1, +- type => defined $opt{logtype} ? $opt{logtype} : 'syslog'); +- +- if(not defined $opt{host}) { +- while(my $sl = $parser->next) { +- process_line($sl); +- } +- } +- else { +- my $host = qr/^$opt{host}$/i; +- while(my $sl = $parser->next) { +- process_line($sl) if $sl->[1] =~ $host; +- } +- } ++ Getopt::Long::Configure('no_ignore_case'); ++ GetOptions(\%opt, 'help|h', 'cat|c', 'logfile|l=s', 'logtype|t=s', 'version|V', ++ 'year|y=i', 'host=s', 'verbose|v', 'daemon|d!', ++ 'daemon_pid|daemon-pid=s', 'daemon_rrd|daemon-rrd=s', ++ 'daemon_log|daemon-log=s', 'ignore-localhost!', 'ignore-host=s@', ++ 'no-mail-rrd', 'no-virus-rrd', 'no-greylist-rrd', 'rrd_name|rrd-name=s', ++ 'rbl-is-spam', 'virbl-is-virus' ++ ) or exit(1); ++ usage if $opt{help}; ++ ++ if($opt{version}) { ++ print "mailgraph $VERSION by david\@schweikert.ch\n"; ++ exit; ++ } ++ ++ $daemon_pidfile = $opt{daemon_pid} if defined $opt{daemon_pid}; ++ $daemon_logfile = $opt{daemon_log} if defined $opt{daemon_log}; ++ $daemon_rrd_dir = $opt{daemon_rrd} if defined $opt{daemon_rrd}; ++ $rrd = $opt{rrd_name}.".rrd" if defined $opt{rrd_name}; ++ $rrd_virus = $opt{rrd_name}."_virus.rrd" if defined $opt{rrd_name}; ++ $rrd_greylist = $opt{rrd_name}."_greylist.rrd" if defined $opt{rrd_name}; ++ ++ # compile --ignore-host regexps ++ if(defined $opt{'ignore-host'}) { ++ for my $ih (@{$opt{'ignore-host'}}) { ++ push @{$opt{'ignore-host-re'}}, qr{\brelay=[^\s,]*$ih}i; ++ } ++ } ++ ++ if($opt{daemon} or $opt{daemon_rrd}) { ++ chdir $daemon_rrd_dir or die "mailgraph: can't chdir to $daemon_rrd_dir: $!"; ++ -w $daemon_rrd_dir or die "mailgraph: can't write to $daemon_rrd_dir\n"; ++ } ++ ++ daemonize if $opt{daemon}; ++ ++ my $logfile = defined $opt{logfile} ? $opt{logfile} : '/var/log/syslog'; ++ my $file; ++ if($opt{cat}) { ++ $file = $logfile; ++ } ++ else { ++ $file = File::Tail->new(name=>$logfile, tail=>-1); ++ } ++ my $parser = new Parse::Syslog($file, year => $opt{year}, arrayref => 1, ++ type => defined $opt{logtype} ? $opt{logtype} : 'syslog'); ++ ++ if(not defined $opt{host}) { ++ while(my $sl = $parser->next) { ++ process_line($sl); ++ } ++ } ++ else { ++ my $host = qr/^$opt{host}$/i; ++ while(my $sl = $parser->next) { ++ process_line($sl) if $sl->[1] =~ $host; ++ } ++ } + } + + sub daemonize() + { +- open STDIN, '/dev/null' or die "mailgraph: can't read /dev/null: $!"; +- if($opt{verbose}) { +- open STDOUT, ">>$daemon_logfile" +- or die "mailgraph: can't write to $daemon_logfile: $!"; +- } +- else { +- open STDOUT, '>/dev/null' +- or die "mailgraph: can't write to /dev/null: $!"; +- } +- defined(my $pid = fork) or die "mailgraph: can't fork: $!"; +- if($pid) { +- # parent +- open PIDFILE, ">$daemon_pidfile" +- or die "mailgraph: can't write to $daemon_pidfile: $!\n"; +- print PIDFILE "$pid\n"; +- close(PIDFILE); +- exit; +- } +- # child +- setsid or die "mailgraph: can't start a new session: $!"; +- open STDERR, '>&STDOUT' or die "mailgraph: can't dup stdout: $!"; ++ open STDIN, '/dev/null' or die "mailgraph: can't read /dev/null: $!"; ++ if($opt{verbose}) { ++ open STDOUT, ">>$daemon_logfile" ++ or die "mailgraph: can't write to $daemon_logfile: $!"; ++ } ++ else { ++ open STDOUT, '>/dev/null' ++ or die "mailgraph: can't write to /dev/null: $!"; ++ } ++ defined(my $pid = fork) or die "mailgraph: can't fork: $!"; ++ if($pid) { ++ # parent ++ open PIDFILE, ">$daemon_pidfile" ++ or die "mailgraph: can't write to $daemon_pidfile: $!\n"; ++ print PIDFILE "$pid\n"; ++ close(PIDFILE); ++ exit; ++ } ++ # child ++ setsid or die "mailgraph: can't start a new session: $!"; ++ open STDERR, '>&STDOUT' or die "mailgraph: can't dup stdout: $!"; + } + + sub init_rrd($) + { +- my $m = shift; +- my $rows = $xpoints/$points_per_sample; +- my $realrows = int($rows*1.1); # ensure that the full range is covered +- my $day_steps = int(3600*24 / ($rrdstep*$rows)); +- # use multiples, otherwise rrdtool could choose the wrong RRA +- my $week_steps = $day_steps*7; +- my $month_steps = $week_steps*5; +- my $year_steps = $month_steps*12; +- +- # mail rrd +- if(! -f $rrd and ! $opt{'only-virus-rrd'}) { +- RRDs::create($rrd, '--start', $m, '--step', $rrdstep, +- 'DS:sent:ABSOLUTE:'.($rrdstep*2).':0:U', +- 'DS:recv:ABSOLUTE:'.($rrdstep*2).':0:U', +- 'DS:bounced:ABSOLUTE:'.($rrdstep*2).':0:U', +- 'DS:rejected:ABSOLUTE:'.($rrdstep*2).':0:U', +- "RRA:AVERAGE:0.5:$day_steps:$realrows", # day +- "RRA:AVERAGE:0.5:$week_steps:$realrows", # week +- "RRA:AVERAGE:0.5:$month_steps:$realrows", # month +- "RRA:AVERAGE:0.5:$year_steps:$realrows", # year +- "RRA:MAX:0.5:$day_steps:$realrows", # day +- "RRA:MAX:0.5:$week_steps:$realrows", # week +- "RRA:MAX:0.5:$month_steps:$realrows", # month +- "RRA:MAX:0.5:$year_steps:$realrows", # year +- ); +- $this_minute = $m; +- } +- elsif(-f $rrd) { +- $this_minute = RRDs::last($rrd) + $rrdstep; +- } +- +- # virus rrd +- if(! -f $rrd_virus and ! $opt{'only-mail-rrd'}) { +- RRDs::create($rrd_virus, '--start', $m, '--step', $rrdstep, +- 'DS:virus:ABSOLUTE:'.($rrdstep*2).':0:U', +- 'DS:spam:ABSOLUTE:'.($rrdstep*2).':0:U', +- "RRA:AVERAGE:0.5:$day_steps:$realrows", # day +- "RRA:AVERAGE:0.5:$week_steps:$realrows", # week +- "RRA:AVERAGE:0.5:$month_steps:$realrows", # month +- "RRA:AVERAGE:0.5:$year_steps:$realrows", # year +- "RRA:MAX:0.5:$day_steps:$realrows", # day +- "RRA:MAX:0.5:$week_steps:$realrows", # week +- "RRA:MAX:0.5:$month_steps:$realrows", # month +- "RRA:MAX:0.5:$year_steps:$realrows", # year +- ); +- } +- elsif(-f $rrd_virus and ! defined $rrd_virus) { +- $this_minute = RRDs::last($rrd_virus) + $rrdstep; +- } ++ my $m = shift; ++ my $rows = $xpoints/$points_per_sample; ++ my $realrows = int($rows*1.1); # ensure that the full range is covered ++ my $day_steps = int(3600*24 / ($rrdstep*$rows)); ++ # use multiples, otherwise rrdtool could choose the wrong RRA ++ my $week_steps = $day_steps*7; ++ my $month_steps = $week_steps*5; ++ my $year_steps = $month_steps*12; ++ ++ # mail rrd ++ if(! -f $rrd and ! $opt{'no-mail-rrd'}) { ++ RRDs::create($rrd, '--start', $m, '--step', $rrdstep, ++ 'DS:sent:ABSOLUTE:'.($rrdstep*2).':0:U', ++ 'DS:recv:ABSOLUTE:'.($rrdstep*2).':0:U', ++ 'DS:bounced:ABSOLUTE:'.($rrdstep*2).':0:U', ++ 'DS:rejected:ABSOLUTE:'.($rrdstep*2).':0:U', ++ "RRA:AVERAGE:0.5:$day_steps:$realrows", # day ++ "RRA:AVERAGE:0.5:$week_steps:$realrows", # week ++ "RRA:AVERAGE:0.5:$month_steps:$realrows", # month ++ "RRA:AVERAGE:0.5:$year_steps:$realrows", # year ++ "RRA:MAX:0.5:$day_steps:$realrows", # day ++ "RRA:MAX:0.5:$week_steps:$realrows", # week ++ "RRA:MAX:0.5:$month_steps:$realrows", # month ++ "RRA:MAX:0.5:$year_steps:$realrows", # year ++ ); ++ $this_minute = $m; ++ } ++ elsif(-f $rrd) { ++ $this_minute = RRDs::last($rrd) + $rrdstep; ++ } ++ ++ # virus rrd ++ if(! -f $rrd_virus and ! $opt{'no-virus-rrd'}) { ++ RRDs::create($rrd_virus, '--start', $m, '--step', $rrdstep, ++ 'DS:virus:ABSOLUTE:'.($rrdstep*2).':0:U', ++ 'DS:spam:ABSOLUTE:'.($rrdstep*2).':0:U', ++ "RRA:AVERAGE:0.5:$day_steps:$realrows", # day ++ "RRA:AVERAGE:0.5:$week_steps:$realrows", # week ++ "RRA:AVERAGE:0.5:$month_steps:$realrows", # month ++ "RRA:AVERAGE:0.5:$year_steps:$realrows", # year ++ "RRA:MAX:0.5:$day_steps:$realrows", # day ++ "RRA:MAX:0.5:$week_steps:$realrows", # week ++ "RRA:MAX:0.5:$month_steps:$realrows", # month ++ "RRA:MAX:0.5:$year_steps:$realrows", # year ++ ); ++ } ++ elsif(-f $rrd_virus and ! defined $rrd_virus) { ++ $this_minute = RRDs::last($rrd_virus) + $rrdstep; ++ } ++ # greylist rrd ++ if(! -f $rrd_greylist and ! $opt{'no-greylist-rrd'}) { ++ RRDs::create($rrd_greylist, '--start', $m, '--step', $rrdstep, ++ 'DS:greylisted:ABSOLUTE:'.($rrdstep*2).':0:U', ++ 'DS:delayed:ABSOLUTE:'.($rrdstep*2).':0:U', ++ "RRA:AVERAGE:0.5:$day_steps:$realrows", # day ++ "RRA:AVERAGE:0.5:$week_steps:$realrows", # week ++ "RRA:AVERAGE:0.5:$month_steps:$realrows", # month ++ "RRA:AVERAGE:0.5:$year_steps:$realrows", # year ++ "RRA:MAX:0.5:$day_steps:$realrows", # day ++ "RRA:MAX:0.5:$week_steps:$realrows", # week ++ "RRA:MAX:0.5:$month_steps:$realrows", # month ++ "RRA:MAX:0.5:$year_steps:$realrows", # year ++ ); ++ $this_minute = $m; ++ } ++ elsif(-f $rrd_greylist and ! defined $rrd_greylist) { ++ $this_minute = RRDs::last($rrd_greylist) + $rrdstep; ++ } + +- $rrd_inited=1; ++ $rrd_inited=1; + } + + sub process_line($) + { +- my $sl = shift; +- my $time = $sl->[0]; +- my $prog = $sl->[2]; +- my $text = $sl->[4]; +- +- if($prog =~ /^postfix\/(.*)/) { +- my $prog = $1; +- if($prog eq 'smtp') { +- if($text =~ /\bstatus=sent\b/) { +- return if $opt{'ignore-localhost'} and +- $text =~ /\brelay=[^\s\[]*\[127\.0\.0\.1\]/; +- if(defined $opt{'ignore-host-re'}) { +- for my $ih (@{$opt{'ignore-host-re'}}) { +- warn "MATCH! $text\n" if $text =~ $ih; +- return if $text =~ $ih; +- } +- } +- event($time, 'sent'); +- } +- elsif($text =~ /\bstatus=bounced\b/) { +- event($time, 'bounced'); +- } +- } +- elsif($prog eq 'local') { +- if($text =~ /\bstatus=bounced\b/) { +- event($time, 'bounced'); +- } +- } +- elsif($prog eq 'smtpd') { +- if($text =~ /^[0-9A-Z]+: client=(\S+)/) { +- my $client = $1; +- return if $opt{'ignore-localhost'} and +- $client =~ /\[127\.0\.0\.1\]$/; +- return if $opt{'ignore-host'} and +- $client =~ /$opt{'ignore-host'}/oi; +- event($time, 'received'); +- } +- elsif($opt{'virbl-is-virus'} and $text =~ /^(?:[0-9A-Z]+: |NOQUEUE: )?reject: .*: 554.* blocked using virbl.dnsbl.bit.nl/) { +- event($time, 'virus'); +- } +- elsif($opt{'rbl-is-spam'} and $text =~ /^(?:[0-9A-Z]+: |NOQUEUE: )?reject: .*: 554.* blocked using/) { +- event($time, 'spam'); +- } +- elsif($text =~ /^(?:[0-9A-Z]+: |NOQUEUE: )?reject: /) { +- event($time, 'rejected'); +- } +- elsif($text =~ /^(?:[0-9A-Z]+: |NOQUEUE: )?milter-reject: /) { +- if($text =~ /Blocked by SpamAssassin/) { +- event($time, 'spam'); +- } +- else { +- event($time, 'rejected'); +- } +- } +- } +- elsif($prog eq 'error') { +- if($text =~ /\bstatus=bounced\b/) { +- event($time, 'bounced'); +- } +- } +- elsif($prog eq 'cleanup') { +- if($text =~ /^[0-9A-Z]+: (?:reject|discard): /) { +- event($time, 'rejected'); +- } +- } +- } +- elsif($prog eq 'sendmail' or $prog eq 'sm-mta') { +- if($text =~ /\bmailer=local\b/ ) { +- event($time, 'received'); +- } ++ my $sl = shift; ++ my $time = $sl->[0]; ++ my $prog = $sl->[2]; ++ my $text = $sl->[4]; ++ ++ if($prog =~ /^postfix\/(.*)/) { ++ my $prog = $1; ++ if($prog eq 'smtp') { ++ if($text =~ /\bstatus=sent\b/) { ++ return if $opt{'ignore-localhost'} and ++ $text =~ /\brelay=[^\s\[]*\[127\.0\.0\.1\]/; ++ if(defined $opt{'ignore-host-re'}) { ++ for my $ih (@{$opt{'ignore-host-re'}}) { ++ warn "MATCH! $text\n" if $text =~ $ih; ++ return if $text =~ $ih; ++ } ++ } ++ event($time, 'sent'); ++ } ++ elsif($text =~ /\bstatus=bounced\b/) { ++ event($time, 'bounced'); ++ } ++ } ++ elsif($prog eq 'local') { ++ if($text =~ /\bstatus=bounced\b/) { ++ event($time, 'bounced'); ++ } ++ } ++ elsif($prog eq 'smtpd' || $prog eq 'postscreen') { ++ if($text =~ /^(?:[\dA-F]+|[\dB-DF-HJ-NP-TV-Zb-df-hj-np-tv-z]+): client=(\S+)/) { ++ my $client = $1; ++ return if $opt{'ignore-localhost'} and ++ $client =~ /\[127\.0\.0\.1\]$/; ++ return if $opt{'ignore-host'} and ++ $client =~ /$opt{'ignore-host'}/oi; ++ event($time, 'received'); ++ } ++ elsif($opt{'virbl-is-virus'} and $text =~ /^(?:[\dA-F]+: |[\dB-DF-HJ-NP-TV-Zb-df-hj-np-tv-z]+: |NOQUEUE: )?reject: .*: 554.* blocked using virbl.dnsbl.bit.nl/) { ++ event($time, 'virus'); ++ } ++ elsif($opt{'rbl-is-spam'} and $text =~ /^(?:[\dA-F]+: |[\dB-DF-HJ-NP-TV-Zb-df-hj-np-tv-z]+: |NOQUEUE: )?reject: .*: 554.* blocked using/) { ++ event($time, 'spam'); ++ } ++ elsif($text =~ /Greylisted/) { ++ event($time, 'greylisted'); ++ } ++ elsif($text =~ /^(?:[\dA-F]+: |[\dB-DF-HJ-NP-TV-Zb-df-hj-np-tv-z]+: |NOQUEUE: )?reject: /) { ++ event($time, 'rejected'); ++ } ++ elsif($text =~ /^(?:[\dA-F]+: |[\dB-DF-HJ-NP-TV-Zb-df-hj-np-tv-z]+: |NOQUEUE: )?milter-reject: /) { ++ if($text =~ /Blocked by SpamAssassin/) { ++ event($time, 'spam'); ++ } ++ else { ++ event($time, 'rejected'); ++ } ++ } ++ } ++ elsif($prog eq 'error') { ++ if($text =~ /\bstatus=bounced\b/) { ++ event($time, 'bounced'); ++ } ++ } ++ elsif($prog eq 'cleanup') { ++ if($text =~ /(?:[\dA-F]+|[\dB-DF-HJ-NP-TV-Zb-df-hj-np-tv-z]+): (?:reject|discard): /) { ++ event($time, 'rejected'); ++ } ++ } ++ } ++ elsif($prog eq 'sendmail' or $prog eq 'sm-mta') { ++ if($text =~ /\bmailer=local\b/ ) { ++ event($time, 'received'); ++ } + elsif($text =~ /\bmailer=relay\b/) { + event($time, 'received'); + } +- elsif($text =~ /\bstat=Sent\b/ ) { +- event($time, 'sent'); +- } ++ elsif($text =~ /\bstat=Sent\b/ ) { ++ event($time, 'sent'); ++ } + elsif($text =~ /\bmailer=esmtp\b/ ) { + event($time, 'sent'); + } +- elsif($text =~ /\bruleset=check_XS4ALL\b/ ) { +- event($time, 'rejected'); +- } +- elsif($text =~ /\blost input channel\b/ ) { +- event($time, 'rejected'); +- } +- elsif($text =~ /\bruleset=check_rcpt\b/ ) { +- event($time, 'rejected'); +- } ++ elsif($text =~ /\bruleset=check_XS4ALL\b/ ) { ++ event($time, 'rejected'); ++ } ++ elsif($text =~ /\blost input channel\b/ ) { ++ event($time, 'rejected'); ++ } ++ elsif($text =~ /\bruleset=check_rcpt\b/ ) { ++ event($time, 'rejected'); ++ } + elsif($text =~ /\bstat=virus\b/ ) { + event($time, 'virus'); + } +- elsif($text =~ /\bruleset=check_relay\b/ ) { +- if (($opt{'virbl-is-virus'}) and ($text =~ /\bivirbl\b/ )) { +- event($time, 'virus'); +- } elsif ($opt{'rbl-is-spam'}) { +- event($time, 'spam'); +- } else { +- event($time, 'rejected'); +- } +- } +- elsif($text =~ /\bsender blocked\b/ ) { +- event($time, 'rejected'); +- } +- elsif($text =~ /\bsender denied\b/ ) { +- event($time, 'rejected'); +- } +- elsif($text =~ /\brecipient denied\b/ ) { +- event($time, 'rejected'); +- } +- elsif($text =~ /\brecipient unknown\b/ ) { +- event($time, 'rejected'); +- } +- elsif($text =~ /\bUser unknown$/i ) { +- event($time, 'bounced'); +- } +- elsif($text =~ /\bMilter:.*\breject=55/ ) { +- event($time, 'rejected'); +- } +- } +- elsif($prog eq 'exim') { +- if($text =~ /^[0-9a-zA-Z]{6}-[0-9a-zA-Z]{6}-[0-9a-zA-Z]{2} <= \S+/) { +- event($time, 'received'); +- } +- elsif($text =~ /^[0-9a-zA-Z]{6}-[0-9a-zA-Z]{6}-[0-9a-zA-Z]{2} => \S+/) { +- event($time, 'sent'); +- } +- elsif($text =~ / rejected because \S+ is in a black list at \S+/) { +- if($opt{'rbl-is-spam'}) { +- event($time, 'spam'); +- } else { +- event($time, 'rejected'); +- } +- } +- elsif($text =~ / rejected RCPT \S+: (Sender verify failed|Unknown user)/) { +- event($time, 'rejected'); +- } +- } +- elsif($prog eq 'amavis' || $prog eq 'amavisd') { +- if( $text =~ /^\([\w-]+\) (Passed|Blocked) SPAM(?:MY)?\b/) { +- if($text !~ /\btag2=/) { # ignore new per-recipient log entry (2.2.0) +- event($time, 'spam'); # since amavisd-new-2004xxxx +- } +- } +- elsif($text =~ /^\([\w-]+\) (Passed|Not-Delivered)\b.*\bquarantine spam/) { +- event($time, 'spam'); # amavisd-new-20030616 and earlier +- } +- elsif($text =~ /^\([\w-]+\) (Passed |Blocked )?INFECTED\b/) { +- if($text !~ /\btag2=/) { +- event($time, 'virus');# Passed|Blocked inserted since 2004xxxx +- } +- } +- elsif($text =~ /^\([\w-]+\) (Passed |Blocked )?BANNED\b/) { +- if($text !~ /\btag2=/) { +- event($time, 'virus'); +- } +- } +- elsif($text =~ /^Virus found\b/) { +- event($time, 'virus');# AMaViS 0.3.12 and amavisd-0.1 +- } +-# elsif($text =~ /^\([\w-]+\) Passed|Blocked BAD-HEADER\b/) { +-# event($time, 'badh'); +-# } +- } +- elsif($prog eq 'vagatefwd') { +- # Vexira antivirus (old) +- if($text =~ /^VIRUS/) { +- event($time, 'virus'); +- } +- } +- elsif($prog eq 'hook') { +- # Vexira antivirus +- if($text =~ /^\*+ Virus\b/) { +- event($time, 'virus'); +- } +- # Vexira antispam +- elsif($text =~ /\bcontains spam\b/) { +- event($time, 'spam'); +- } +- } +- elsif($prog eq 'avgatefwd' or $prog eq 'avmailgate.bin') { +- # AntiVir MailGate +- if($text =~ /^Alert!/) { +- event($time, 'virus'); +- } +- elsif($text =~ /blocked\.$/) { +- event($time, 'virus'); +- } +- } +- elsif($prog eq 'avcheck') { +- # avcheck +- if($text =~ /^infected/) { +- event($time, 'virus'); +- } +- } +- elsif($prog eq 'spamd') { +- if($text =~ /^(?:spamd: )?identified spam/) { +- event($time, 'spam'); +- } +- # ClamAV SpamAssassin-plugin +- elsif($text =~ /(?:result: )?CLAMAV/) { +- event($time, 'virus'); +- } +- } +- elsif($prog eq 'dspam') { +- if($text =~ /spam detected from/) { +- event($time, 'spam'); +- } +- } +- elsif($prog eq 'spamproxyd' or $prog eq 'spampd') { +- if($text =~ /^\s*SPAM/ or $text =~ /^identified spam/) { +- event($time, 'spam'); +- } +- } +- elsif($prog eq 'drweb-postfix') { +- # DrWeb +- if($text =~ /infected/) { +- event($time, 'virus'); +- } +- } +- elsif($prog eq 'BlackHole') { +- if($text =~ /Virus/) { +- event($time, 'virus'); +- } +- if($text =~ /(?:RBL|Razor|Spam)/) { +- event($time, 'spam'); +- } +- } +- elsif($prog eq 'MailScanner') { +- if($text =~ /(Virus Scanning: Found)/ ) { +- event($time, 'virus'); +- } +- elsif($text =~ /Bounce to/ ) { +- event($time, 'bounced'); +- } +- elsif($text =~ /^Spam Checks: Found ([0-9]+) spam messages/) { +- my $cnt = $1; +- for (my $i=0; $i<$cnt; $i++) { +- event($time, 'spam'); +- } +- } +- } +- elsif($prog eq 'clamsmtpd') { +- if($text =~ /status=VIRUS/) { +- event($time, 'virus'); +- } +- } +- elsif($prog eq 'clamav-milter') { +- if($text =~ /Intercepted/) { +- event($time, 'virus'); +- } +- } +- # uncommment for clamassassin: +- #elsif($prog eq 'clamd') { +- # if($text =~ /^stream: .* FOUND$/) { +- # event($time, 'virus'); +- # } +- #} +- elsif ($prog eq 'smtp-vilter') { +- if ($text =~ /clamd: found/) { +- event($time, 'virus'); +- } +- } +- elsif($prog eq 'avmilter') { +- # AntiVir Milter +- if($text =~ /^Alert!/) { +- event($time, 'virus'); +- } +- elsif($text =~ /blocked\.$/) { +- event($time, 'virus'); +- } +- } +- elsif($prog eq 'bogofilter') { +- if($text =~ /Spam/) { +- event($time, 'spam'); +- } +- } +- elsif($prog eq 'filter-module') { +- if($text =~ /\bspam_status\=(?:yes|spam)/) { +- event($time, 'spam'); +- } +- } +- elsif($prog eq 'sta_scanner') { +- if($text =~ /^[0-9A-F]+: virus/) { +- event($time, 'virus'); +- } +- } ++ elsif($text =~ /\bruleset=check_relay\b/ ) { ++ if (($opt{'virbl-is-virus'}) and ($text =~ /\bivirbl\b/ )) { ++ event($time, 'virus'); ++ } elsif ($opt{'rbl-is-spam'}) { ++ event($time, 'spam'); ++ } else { ++ event($time, 'rejected'); ++ } ++ } ++ elsif($text =~ /\bsender blocked\b/ ) { ++ event($time, 'rejected'); ++ } ++ elsif($text =~ /\bsender denied\b/ ) { ++ event($time, 'rejected'); ++ } ++ elsif($text =~ /\brecipient denied\b/ ) { ++ event($time, 'rejected'); ++ } ++ elsif($text =~ /\brecipient unknown\b/ ) { ++ event($time, 'rejected'); ++ } ++ elsif($text =~ /\bUser unknown$/i ) { ++ event($time, 'bounced'); ++ } ++ elsif($text =~ /\bMilter:.*\breject=55/ ) { ++ event($time, 'rejected'); ++ } ++ } ++ elsif($prog eq 'exim') { ++ if($text =~ /^[0-9a-zA-Z]{6}-[0-9a-zA-Z]{6}-[0-9a-zA-Z]{2} <= \S+/) { ++ event($time, 'received'); ++ } ++ elsif($text =~ /^[0-9a-zA-Z]{6}-[0-9a-zA-Z]{6}-[0-9a-zA-Z]{2} => \S+/) { ++ event($time, 'sent'); ++ } ++ elsif($text =~ / rejected because \S+ is in a black list at \S+/) { ++ if($opt{'rbl-is-spam'}) { ++ event($time, 'spam'); ++ } else { ++ event($time, 'rejected'); ++ } ++ } ++ elsif($text =~ / rejected RCPT \S+: (Sender verify failed|Unknown user)/) { ++ event($time, 'rejected'); ++ } ++ } ++ elsif($prog eq 'amavis' || $prog eq 'amavisd') { ++ if( $text =~ /^\([\w-]+\) (Passed|Blocked) SPAM(?:MY)?\b/) { ++ if($text !~ /\btag2=/) { # ignore new per-recipient log entry (2.2.0) ++ event($time, 'spam'); # since amavisd-new-2004xxxx ++ } ++ } ++ elsif($text =~ /^\([\w-]+\) (Passed|Not-Delivered)\b.*\bquarantine spam/) { ++ event($time, 'spam'); # amavisd-new-20030616 and earlier ++ } ++ elsif($text =~ /^\([\w-]+\) (Passed |Blocked )?INFECTED\b/) { ++ if($text !~ /\btag2=/) { ++ event($time, 'virus');# Passed|Blocked inserted since 2004xxxx ++ } ++ } ++ elsif($text =~ /^\([\w-]+\) (Passed |Blocked )?BANNED\b/) { ++ if($text !~ /\btag2=/) { ++ event($time, 'virus'); ++ } ++ } ++ elsif($text =~ /^Virus found\b/) { ++ event($time, 'virus');# AMaViS 0.3.12 and amavisd-0.1 ++ } ++# elsif($text =~ /^\([\w-]+\) Passed|Blocked BAD-HEADER\b/) { ++# event($time, 'badh'); ++# } ++ } ++ elsif($prog eq 'vagatefwd') { ++ # Vexira antivirus (old) ++ if($text =~ /^VIRUS/) { ++ event($time, 'virus'); ++ } ++ } ++ elsif($prog eq 'hook') { ++ # Vexira antivirus ++ if($text =~ /^\*+ Virus\b/) { ++ event($time, 'virus'); ++ } ++ # Vexira antispam ++ elsif($text =~ /\bcontains spam\b/) { ++ event($time, 'spam'); ++ } ++ } ++ elsif($prog eq 'avgatefwd' or $prog eq 'avmailgate.bin') { ++ # AntiVir MailGate ++ if($text =~ /^Alert!/) { ++ event($time, 'virus'); ++ } ++ elsif($text =~ /blocked\.$/) { ++ event($time, 'virus'); ++ } ++ } ++ elsif($prog eq 'avcheck') { ++ # avcheck ++ if($text =~ /^infected/) { ++ event($time, 'virus'); ++ } ++ } ++ elsif($prog eq 'spamd') { ++ if($text =~ /^(?:spamd: )?identified spam/) { ++ event($time, 'spam'); ++ } ++ # ClamAV SpamAssassin-plugin ++ elsif($text =~ /(?:result: )?CLAMAV/) { ++ event($time, 'virus'); ++ } ++ } ++ elsif($prog eq 'dspam') { ++ if($text =~ /spam detected from/) { ++ event($time, 'spam'); ++ } ++ elsif($text =~ /infected message from/) { ++ event($time, 'virus'); ++ } ++ } ++ elsif($prog eq 'spamproxyd' or $prog eq 'spampd') { ++ if($text =~ /^\s*SPAM/ or $text =~ /^identified spam/) { ++ event($time, 'spam'); ++ } ++ } ++ elsif($prog eq 'drweb-postfix') { ++ # DrWeb ++ if($text =~ /infected/) { ++ event($time, 'virus'); ++ } ++ } ++ elsif($prog eq 'BlackHole') { ++ if($text =~ /Virus/) { ++ event($time, 'virus'); ++ } ++ if($text =~ /(?:RBL|Razor|Spam)/) { ++ event($time, 'spam'); ++ } ++ } ++ elsif($prog eq 'MailScanner') { ++ if($text =~ /(Virus Scanning: Found)/ ) { ++ event($time, 'virus'); ++ } ++ elsif($text =~ /Bounce to/ ) { ++ event($time, 'bounced'); ++ } ++ elsif($text =~ /^Spam Checks: Found ([0-9]+) spam messages/) { ++ my $cnt = $1; ++ for (my $i=0; $i<$cnt; $i++) { ++ event($time, 'spam'); ++ } ++ } ++ } ++ elsif($prog eq 'clamsmtpd') { ++ if($text =~ /status=VIRUS/) { ++ event($time, 'virus'); ++ } ++ } ++ elsif($prog eq 'clamav-milter') { ++ if($text =~ /Intercepted/) { ++ event($time, 'virus'); ++ } ++ elsif($text =~ /Message.*infected by/) { ++ event($time, 'virus'); ++ } ++ } ++ # uncommment for clamassassin: ++ #elsif($prog eq 'clamd') { ++ # if($text =~ /^stream: .* FOUND$/) { ++ # event($time, 'virus'); ++ # } ++ #} ++ elsif ($prog eq 'smtp-vilter') { ++ if ($text =~ /clamd: found/) { ++ event($time, 'virus'); ++ } ++ } ++ elsif($prog eq 'avmilter') { ++ # AntiVir Milter ++ if($text =~ /^Alert!/) { ++ event($time, 'virus'); ++ } ++ elsif($text =~ /blocked\.$/) { ++ event($time, 'virus'); ++ } ++ } ++ elsif($prog eq 'bogofilter') { ++ if($text =~ /Spam/) { ++ event($time, 'spam'); ++ } ++ } ++ elsif($prog eq 'filter-module') { ++ if($text =~ /\bspam_status\=(?:yes|spam)/) { ++ event($time, 'spam'); ++ } ++ } ++ elsif($prog eq 'sta_scanner') { ++ if($text =~ /^[0-9A-F]+: virus/) { ++ event($time, 'virus'); ++ } ++ } ++ elsif($prog eq 'postgrey') { ++ # Old versions (up to 1.27) ++ if($text =~ /delayed [0-9]+ seconds: client/) { ++ event($time, 'delayed'); ++ } ++ # New versions (from 1.28) ++ if($text =~ /delay=[0-9]+/) { ++ event($time, 'delayed'); ++ } ++ } ++ elsif($prog eq 'grossd') { ++ if($text =~ /a\=greylist/) { ++ event($time, 'greylisted'); ++ } ++ } + } + + sub event($$) + { +- my ($t, $type) = @_; +- update($t) and $sum{$type}++; ++ my ($t, $type) = @_; ++ update($t) and $sum{$type}++; + } + + # returns 1 if $sum should be updated + sub update($) + { +- my $t = shift; +- my $m = $t - $t%$rrdstep; +- init_rrd($m) unless $rrd_inited; +- return 1 if $m == $this_minute; +- return 0 if $m < $this_minute; +- +- print "update $this_minute:$sum{sent}:$sum{received}:$sum{bounced}:$sum{rejected}:$sum{virus}:$sum{spam}\n" if $opt{verbose}; +- RRDs::update $rrd, "$this_minute:$sum{sent}:$sum{received}:$sum{bounced}:$sum{rejected}" unless $opt{'only-virus-rrd'}; +- RRDs::update $rrd_virus, "$this_minute:$sum{virus}:$sum{spam}" unless $opt{'only-mail-rrd'}; +- if($m > $this_minute+$rrdstep) { +- for(my $sm=$this_minute+$rrdstep;$sm<$m;$sm+=$rrdstep) { +- print "update $sm:0:0:0:0:0:0 (SKIP)\n" if $opt{verbose}; +- RRDs::update $rrd, "$sm:0:0:0:0" unless $opt{'only-virus-rrd'}; +- RRDs::update $rrd_virus, "$sm:0:0" unless $opt{'only-mail-rrd'}; +- } +- } +- $this_minute = $m; +- $sum{sent}=0; +- $sum{received}=0; +- $sum{bounced}=0; +- $sum{rejected}=0; +- $sum{virus}=0; +- $sum{spam}=0; +- return 1; ++ my $t = shift; ++ my $m = $t - $t%$rrdstep; ++ init_rrd($m) unless $rrd_inited; ++ return 1 if $m == $this_minute; ++ return 0 if $m < $this_minute; ++ ++ print "update $this_minute:$sum{sent}:$sum{received}:$sum{bounced}:$sum{rejected}:$sum{virus}:$sum{spam}:$sum{greylisted}:$sum{delayed}\n" if $opt{verbose}; ++ RRDs::update $rrd, "$this_minute:$sum{sent}:$sum{received}:$sum{bounced}:$sum{rejected}" unless $opt{'no-mail-rrd'}; ++ RRDs::update $rrd_virus, "$this_minute:$sum{virus}:$sum{spam}" unless $opt{'no-virus-rrd'}; ++ RRDs::update $rrd_greylist, "$this_minute:$sum{greylisted}:$sum{delayed}" unless $opt{'no-greylist-rrd'}; ++ if($m > $this_minute+$rrdstep) { ++ for(my $sm=$this_minute+$rrdstep;$sm<$m;$sm+=$rrdstep) { ++ print "update $sm:0:0:0:0:0:0:0:0 (SKIP)\n" if $opt{verbose}; ++ RRDs::update $rrd, "$sm:0:0:0:0" unless $opt{'no-mail-rrd'}; ++ RRDs::update $rrd_virus, "$sm:0:0" unless $opt{'no-virus-rrd'}; ++ RRDs::update $rrd_greylist, "$sm:0:0" unless $opt{'no-greylist-rrd'}; ++ } ++ } ++ $this_minute = $m; ++ $sum{sent}=0; ++ $sum{received}=0; ++ $sum{bounced}=0; ++ $sum{rejected}=0; ++ $sum{virus}=0; ++ $sum{spam}=0; ++ $sum{greylisted}=0; ++ $sum{delayed}=0; ++ return 1; + } + + main; +@@ -919,8 +993,9 @@ B [I...] + --daemon-log=FILE write verbose-log to FILE instead of /var/log/mailgraph.log + --ignore-localhost ignore mail to/from localhost (used for virus scanner) + --ignore-host=HOST ignore mail to/from HOST regexp (used for virus scanner) +- --only-mail-rrd update only the mail rrd +- --only-virus-rrd update only the virus rrd ++ --no-mail-rrd do not update mail rrd ++ --no-virus-rrd do not update virus rrd ++ --no-greylist-rrd do not update greylist rrd + --rrd-name=NAME use NAME.rrd and NAME_virus.rrd for the rrd files + --rbl-is-spam count rbl rejects as spam + --virbl-is-virus count virbl rejects as viruses +@@ -940,6 +1015,10 @@ The following types can be given to --lo + + Traditional "syslog" (default) + ++=item rsyslog ++ ++High precision format "rsyslog" ++ + =item metalog + + Metalog (see http://metalog.sourceforge.net/) +@@ -950,6 +1029,7 @@ Metalog (see http://metalog.sourceforge. + + Copyright (c) 2000-2007 by ETH Zurich + Copyright (c) 2000-2007 by David Schweikert ++Copyright (c) 2018 by M.D. Klapwijk + + =head1 LICENSE + +@@ -973,4 +1053,4 @@ Sdavid@schweikert + + =cut + +-# vi: sw=8 ++# vi: sw=8 +\ No newline at end of file -- cgit v1.2.3 From 7cdc0b1dc9201f671abe70c19d55010ab111a599 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Sun, 24 Sep 2023 16:18:40 +0200 Subject: Remove quilt backup file --- debian/patches/0100-new_syslog_format.patch~ | 1239 -------------------------- 1 file changed, 1239 deletions(-) delete mode 100644 debian/patches/0100-new_syslog_format.patch~ diff --git a/debian/patches/0100-new_syslog_format.patch~ b/debian/patches/0100-new_syslog_format.patch~ deleted file mode 100644 index 5344f07..0000000 --- a/debian/patches/0100-new_syslog_format.patch~ +++ /dev/null @@ -1,1239 +0,0 @@ -Description: Add new syslog format -Author: M.D. Klapwijk -Origin: https://gist.github.com/mdklapwijk/4f8d2fc39f09f4aa615cbf8ffae0379a -Bug: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1051496 -Forwarded: not-needed -Last-Update: 2023-09-23 ---- -This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ -Index: trunk/mailgraph.pl -=================================================================== ---- trunk.orig/mailgraph.pl -+++ trunk/mailgraph.pl -@@ -5,6 +5,10 @@ - # copyright (c) 2000-2007 David Schweikert - # released under the GNU General Public License - -+# modifications to handle rsyslog high precision format -+# copyright (c) 2018 by M.D. Klapwijk -+# released under the GNU General Public License -+ - ######## Parse::Syslog 1.09 (automatically embedded) ######## - package Parse::Syslog; - use Carp; -@@ -85,7 +89,7 @@ sub str2time($$$$$$$$) - # - compensate if yes - # note that we assume that the DST-switch goes like this: - # time 1:00 1:30 2:00 2:30 2:00 2:30 3:00 3:30 -- # stamp 1 2 3 4 3 3 7 8 -+ # stamp 1 2 3 4 3 3 7 8 - # comp. 0 0 0 0 2 2 0 0 - # result 1 2 3 4 5 6 7 8 - # old Time::Local versions behave differently (1 2 5 6 5 6 7 8) -@@ -202,27 +206,46 @@ sub _next_syslog($) - } - my $file = $self->{file}; - line: while(defined (my $str = $self->_next_line)) { -- # date, time and host -- $str =~ /^ -- (\S{3})\s+(\d+) # date -- 1, 2 -- \s -- (\d+):(\d+):(\d+) # time -- 3, 4, 5 -- (?:\s<\w+\.\w+>)? # FreeBSD's verbose-mode -- \s -- ([-\w\.\@:]+) # host -- 6 -- \s+ -- (?:\[LOG_[A-Z]+\]\s+)? # FreeBSD -- (.*) # text -- 7 -- $/x or do -- { -- warn "WARNING: line not in syslog format: $str"; -- next line; -- }; -- my $mon = $months_map{$1}; -- defined $mon or croak "unknown month $1\n"; -- $self->_year_increment($mon); -+ # date, time and host -+ my ($year, $mon, $day, $hour, $min, $sec, $host, $text); -+ if($self->{type} eq 'rsyslog') { -+ ($year, $mon, $day, $hour, $min, $sec, $host, $text) = $str =~ /^ -+ (\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)\S+ # datetime -+ \s+ -+ (\S+) # host -+ \s+ -+ (.*) # text -+ $/x or do -+ { -+ warn "WARNING: line not in high precision rsyslog format: $str"; -+ next line; -+ }; -+ $mon--; -+ $self->{year}=$year; -+ } -+ else { -+ my($montxt, $mon); -+ ($montxt, $day, $hour, $min, $sec, $host, $text) = $str =~ /^ -+ (\S{3})\s+(\d+) # date -+ \s -+ (\d+):(\d+):(\d+) # time -+ (?:\s<\w+\.\w+>)? # FreeBSD's verbose-mode -+ \s -+ ([-\w\.\@:]+) # host -+ \s+ -+ (?:\[LOG_[A-Z]+\]\s+)? # FreeBSD -+ (.*) # text -+ $/x or do -+ { -+ warn "WARNING: line not in syslog format: $str"; -+ next line; -+ }; -+ $mon = $months_map{$montxt}; -+ defined $mon or croak "unknown month $montxt\n"; -+ $self->_year_increment($mon); -+ } - # convert to unix time -- my $time = $self->str2time($5,$4,$3,$2,$mon,$self->{year}-1900,$self->{GMT}); -+ my $time = $self->str2time($sec,$min,$hour,$day,$mon,$self->{year}-1900,$self->{GMT}); - if(not $self->{allow_future}) { - # accept maximum one day in the present future - if($time - time > 86400) { -@@ -230,7 +253,6 @@ sub _next_syslog($) - next line; - } - } -- my ($host, $text) = ($6, $7); - # last message repeated ... times - if($text =~ /^(?:last message repeated|above message repeats) (\d+) time/) { - next line if defined $self->{repeat} and not $self->{repeat}; -@@ -264,11 +286,11 @@ sub _next_syslog($) - }; - if($self->{arrayref}) { - $self->{_last_data}{$host} = [ -- $time, # 0: timestamp -- $host, # 1: host -- $1, # 2: program -- $2, # 3: pid -- $6, # 4: text -+ $time, # 0: timestamp -+ $host, # 1: host -+ $1, # 2: program -+ $2, # 3: pid -+ $6, # 4: text - ]; - } - else { -@@ -292,12 +314,12 @@ sub _next_metalog($) - my ($self) = @_; - my $file = $self->{file}; - line: while(my $str = $self->_next_line) { -- # date, time and host -- $str =~ /^ -+ # date, time and host -+ $str =~ /^ - (\S{3})\s+(\d+) # date -- 1, 2 - \s - (\d+):(\d+):(\d+) # time -- 3, 4, 5 -- # host is not logged -+ # host is not logged - \s+ - (.*) # text -- 6 - $/x or do -@@ -310,22 +332,22 @@ sub _next_metalog($) - $self->_year_increment($mon); - # convert to unix time - my $time = $self->str2time($5,$4,$3,$2,$mon,$self->{year}-1900,$self->{GMT}); -- my $text = $6; -+ my $text = $6; - $text =~ /^ - \[(.*?)\] # program -- 1 -- # no PID -- \s+ -+ # no PID -+ \s+ - (.*) # text -- 2 - $/x or do - { -- warn "WARNING: text line not in metalog format: $text ($str)"; -+ warn "WARNING: text line not in metalog format: $text ($str)"; - next line; - }; - if($self->{arrayref}) { - return [ -- $time, # 0: timestamp -- 'localhost', # 1: host -- $1, # 2: program -+ $time, # 0: timestamp -+ 'localhost', # 1: host -+ $1, # 2: program - undef, # 3: (no) pid - $2, # 4: text - ]; -@@ -344,7 +366,7 @@ sub _next_metalog($) - sub next($) - { - my ($self) = @_; -- if($self->{type} eq 'syslog') { -+ if($self->{type} eq 'syslog' || $self->{type} eq 'rsyslog') { - return $self->_next_syslog(); - } - elsif($self->{type} eq 'metalog') { -@@ -373,15 +395,16 @@ my $points_per_sample = 3; - - my $daemon_logfile = '/var/log/mailgraph.log'; - my $daemon_pidfile = '/var/run/mailgraph.pid'; --my $daemon_rrd_dir = '/var/log'; -+my $daemon_rrd_dir = '/var/lib/mailgraph'; - - # global variables - my $logfile; - my $rrd = "mailgraph.rrd"; - my $rrd_virus = "mailgraph_virus.rrd"; -+my $rrd_greylist = "mailgraph_greylist.rrd"; - my $year; - my $this_minute; --my %sum = ( sent => 0, received => 0, bounced => 0, rejected => 0, virus => 0, spam => 0 ); -+my %sum = ( sent => 0, received => 0, bounced => 0, rejected => 0, virus => 0, spam => 0, greylisted => 0, delayed => 0); - my $rrd_inited=0; - - my %opt = (); -@@ -395,499 +418,550 @@ sub event_bounced($); - sub event_rejected($); - sub event_virus($); - sub event_spam($); -+sub event_greylisted($); -+sub event_delayed($); - sub init_rrd($); - sub update($); - - sub usage - { -- print "usage: mailgraph [*options*]\n\n"; -- print " -h, --help display this help and exit\n"; -- print " -v, --verbose be verbose about what you do\n"; -- print " -V, --version output version information and exit\n"; -- print " -c, --cat causes the logfile to be only read and not monitored\n"; -- print " -l, --logfile f monitor logfile f instead of /var/log/syslog\n"; -- print " -t, --logtype t set logfile's type (default: syslog)\n"; -- print " -y, --year starting year of the log file (default: current year)\n"; -- print " --host=HOST use only entries for HOST (regexp) in syslog\n"; -- print " -d, --daemon start in the background\n"; -- print " --daemon-pid=FILE write PID to FILE instead of /var/run/mailgraph.pid\n"; -- print " --daemon-rrd=DIR write RRDs to DIR instead of /var/log\n"; -- print " --daemon-log=FILE write verbose-log to FILE instead of /var/log/mailgraph.log\n"; -- print " --ignore-localhost ignore mail to/from localhost (used for virus scanner)\n"; -- print " --ignore-host=HOST ignore mail to/from HOST regexp (used for virus scanner)\n"; -- print " --only-mail-rrd update only the mail rrd\n"; -- print " --only-virus-rrd update only the virus rrd\n"; -- print " --rrd-name=NAME use NAME.rrd and NAME_virus.rrd for the rrd files\n"; -- print " --rbl-is-spam count rbl rejects as spam\n"; -- print " --virbl-is-virus count virbl rejects as viruses\n"; -+ print "usage: mailgraph [*options*]\n\n"; -+ print " -h, --help display this help and exit\n"; -+ print " -v, --verbose be verbose about what you do\n"; -+ print " -V, --version output version information and exit\n"; -+ print " -c, --cat causes the logfile to be only read and not monitored\n"; -+ print " -l, --logfile f monitor logfile f instead of /var/log/syslog\n"; -+ print " -t, --logtype t set logfile's type (default: syslog)\n"; -+ print " -y, --year starting year of the log file (default: current year)\n"; -+ print " --host=HOST use only entries for HOST (regexp) in syslog\n"; -+ print " -d, --daemon start in the background\n"; -+ print " --daemon-pid=FILE write PID to FILE instead of /var/run/mailgraph.pid\n"; -+ print " --daemon-rrd=DIR write RRDs to DIR instead of /var/lib/mailgraph\n"; -+ print " --daemon-log=FILE write verbose-log to FILE instead of /var/log/mailgraph.log\n"; -+ print " --ignore-localhost ignore mail to/from localhost (used for virus scanner)\n"; -+ print " --ignore-host=HOST ignore mail to/from HOST regexp (used for virus scanner)\n"; -+ print " --no-mail-rrd no update mail rrd\n"; -+ print " --no-virus-rrd no update virus rrd\n"; -+ print " --no-greylist-rrd no update greylist rrd\n"; -+ print " --rrd-name=NAME use NAME.rrd and NAME_virus.rrd for the rrd files\n"; -+ print " --rbl-is-spam count rbl rejects as spam\n"; -+ print " --virbl-is-virus count virbl rejects as viruses\n"; - -- exit; -+ exit; - } - - sub main - { -- Getopt::Long::Configure('no_ignore_case'); -- GetOptions(\%opt, 'help|h', 'cat|c', 'logfile|l=s', 'logtype|t=s', 'version|V', -- 'year|y=i', 'host=s', 'verbose|v', 'daemon|d!', -- 'daemon_pid|daemon-pid=s', 'daemon_rrd|daemon-rrd=s', -- 'daemon_log|daemon-log=s', 'ignore-localhost!', 'ignore-host=s@', -- 'only-mail-rrd', 'only-virus-rrd', 'rrd_name|rrd-name=s', -- 'rbl-is-spam', 'virbl-is-virus' -- ) or exit(1); -- usage if $opt{help}; -- -- if($opt{version}) { -- print "mailgraph $VERSION by david\@schweikert.ch\n"; -- exit; -- } -- -- $daemon_pidfile = $opt{daemon_pid} if defined $opt{daemon_pid}; -- $daemon_logfile = $opt{daemon_log} if defined $opt{daemon_log}; -- $daemon_rrd_dir = $opt{daemon_rrd} if defined $opt{daemon_rrd}; -- $rrd = $opt{rrd_name}.".rrd" if defined $opt{rrd_name}; -- $rrd_virus = $opt{rrd_name}."_virus.rrd" if defined $opt{rrd_name}; -- -- # compile --ignore-host regexps -- if(defined $opt{'ignore-host'}) { -- for my $ih (@{$opt{'ignore-host'}}) { -- push @{$opt{'ignore-host-re'}}, qr{\brelay=[^\s,]*$ih}i; -- } -- } -- -- if($opt{daemon} or $opt{daemon_rrd}) { -- chdir $daemon_rrd_dir or die "mailgraph: can't chdir to $daemon_rrd_dir: $!"; -- -w $daemon_rrd_dir or die "mailgraph: can't write to $daemon_rrd_dir\n"; -- } -- -- daemonize if $opt{daemon}; -- -- my $logfile = defined $opt{logfile} ? $opt{logfile} : '/var/log/syslog'; -- my $file; -- if($opt{cat}) { -- $file = $logfile; -- } -- else { -- $file = File::Tail->new(name=>$logfile, tail=>-1); -- } -- my $parser = new Parse::Syslog($file, year => $opt{year}, arrayref => 1, -- type => defined $opt{logtype} ? $opt{logtype} : 'syslog'); -- -- if(not defined $opt{host}) { -- while(my $sl = $parser->next) { -- process_line($sl); -- } -- } -- else { -- my $host = qr/^$opt{host}$/i; -- while(my $sl = $parser->next) { -- process_line($sl) if $sl->[1] =~ $host; -- } -- } -+ Getopt::Long::Configure('no_ignore_case'); -+ GetOptions(\%opt, 'help|h', 'cat|c', 'logfile|l=s', 'logtype|t=s', 'version|V', -+ 'year|y=i', 'host=s', 'verbose|v', 'daemon|d!', -+ 'daemon_pid|daemon-pid=s', 'daemon_rrd|daemon-rrd=s', -+ 'daemon_log|daemon-log=s', 'ignore-localhost!', 'ignore-host=s@', -+ 'no-mail-rrd', 'no-virus-rrd', 'no-greylist-rrd', 'rrd_name|rrd-name=s', -+ 'rbl-is-spam', 'virbl-is-virus' -+ ) or exit(1); -+ usage if $opt{help}; -+ -+ if($opt{version}) { -+ print "mailgraph $VERSION by david\@schweikert.ch\n"; -+ exit; -+ } -+ -+ $daemon_pidfile = $opt{daemon_pid} if defined $opt{daemon_pid}; -+ $daemon_logfile = $opt{daemon_log} if defined $opt{daemon_log}; -+ $daemon_rrd_dir = $opt{daemon_rrd} if defined $opt{daemon_rrd}; -+ $rrd = $opt{rrd_name}.".rrd" if defined $opt{rrd_name}; -+ $rrd_virus = $opt{rrd_name}."_virus.rrd" if defined $opt{rrd_name}; -+ $rrd_greylist = $opt{rrd_name}."_greylist.rrd" if defined $opt{rrd_name}; -+ -+ # compile --ignore-host regexps -+ if(defined $opt{'ignore-host'}) { -+ for my $ih (@{$opt{'ignore-host'}}) { -+ push @{$opt{'ignore-host-re'}}, qr{\brelay=[^\s,]*$ih}i; -+ } -+ } -+ -+ if($opt{daemon} or $opt{daemon_rrd}) { -+ chdir $daemon_rrd_dir or die "mailgraph: can't chdir to $daemon_rrd_dir: $!"; -+ -w $daemon_rrd_dir or die "mailgraph: can't write to $daemon_rrd_dir\n"; -+ } -+ -+ daemonize if $opt{daemon}; -+ -+ my $logfile = defined $opt{logfile} ? $opt{logfile} : '/var/log/syslog'; -+ my $file; -+ if($opt{cat}) { -+ $file = $logfile; -+ } -+ else { -+ $file = File::Tail->new(name=>$logfile, tail=>-1); -+ } -+ my $parser = new Parse::Syslog($file, year => $opt{year}, arrayref => 1, -+ type => defined $opt{logtype} ? $opt{logtype} : 'syslog'); -+ -+ if(not defined $opt{host}) { -+ while(my $sl = $parser->next) { -+ process_line($sl); -+ } -+ } -+ else { -+ my $host = qr/^$opt{host}$/i; -+ while(my $sl = $parser->next) { -+ process_line($sl) if $sl->[1] =~ $host; -+ } -+ } - } - - sub daemonize() - { -- open STDIN, '/dev/null' or die "mailgraph: can't read /dev/null: $!"; -- if($opt{verbose}) { -- open STDOUT, ">>$daemon_logfile" -- or die "mailgraph: can't write to $daemon_logfile: $!"; -- } -- else { -- open STDOUT, '>/dev/null' -- or die "mailgraph: can't write to /dev/null: $!"; -- } -- defined(my $pid = fork) or die "mailgraph: can't fork: $!"; -- if($pid) { -- # parent -- open PIDFILE, ">$daemon_pidfile" -- or die "mailgraph: can't write to $daemon_pidfile: $!\n"; -- print PIDFILE "$pid\n"; -- close(PIDFILE); -- exit; -- } -- # child -- setsid or die "mailgraph: can't start a new session: $!"; -- open STDERR, '>&STDOUT' or die "mailgraph: can't dup stdout: $!"; -+ open STDIN, '/dev/null' or die "mailgraph: can't read /dev/null: $!"; -+ if($opt{verbose}) { -+ open STDOUT, ">>$daemon_logfile" -+ or die "mailgraph: can't write to $daemon_logfile: $!"; -+ } -+ else { -+ open STDOUT, '>/dev/null' -+ or die "mailgraph: can't write to /dev/null: $!"; -+ } -+ defined(my $pid = fork) or die "mailgraph: can't fork: $!"; -+ if($pid) { -+ # parent -+ open PIDFILE, ">$daemon_pidfile" -+ or die "mailgraph: can't write to $daemon_pidfile: $!\n"; -+ print PIDFILE "$pid\n"; -+ close(PIDFILE); -+ exit; -+ } -+ # child -+ setsid or die "mailgraph: can't start a new session: $!"; -+ open STDERR, '>&STDOUT' or die "mailgraph: can't dup stdout: $!"; - } - - sub init_rrd($) - { -- my $m = shift; -- my $rows = $xpoints/$points_per_sample; -- my $realrows = int($rows*1.1); # ensure that the full range is covered -- my $day_steps = int(3600*24 / ($rrdstep*$rows)); -- # use multiples, otherwise rrdtool could choose the wrong RRA -- my $week_steps = $day_steps*7; -- my $month_steps = $week_steps*5; -- my $year_steps = $month_steps*12; -- -- # mail rrd -- if(! -f $rrd and ! $opt{'only-virus-rrd'}) { -- RRDs::create($rrd, '--start', $m, '--step', $rrdstep, -- 'DS:sent:ABSOLUTE:'.($rrdstep*2).':0:U', -- 'DS:recv:ABSOLUTE:'.($rrdstep*2).':0:U', -- 'DS:bounced:ABSOLUTE:'.($rrdstep*2).':0:U', -- 'DS:rejected:ABSOLUTE:'.($rrdstep*2).':0:U', -- "RRA:AVERAGE:0.5:$day_steps:$realrows", # day -- "RRA:AVERAGE:0.5:$week_steps:$realrows", # week -- "RRA:AVERAGE:0.5:$month_steps:$realrows", # month -- "RRA:AVERAGE:0.5:$year_steps:$realrows", # year -- "RRA:MAX:0.5:$day_steps:$realrows", # day -- "RRA:MAX:0.5:$week_steps:$realrows", # week -- "RRA:MAX:0.5:$month_steps:$realrows", # month -- "RRA:MAX:0.5:$year_steps:$realrows", # year -- ); -- $this_minute = $m; -- } -- elsif(-f $rrd) { -- $this_minute = RRDs::last($rrd) + $rrdstep; -- } -- -- # virus rrd -- if(! -f $rrd_virus and ! $opt{'only-mail-rrd'}) { -- RRDs::create($rrd_virus, '--start', $m, '--step', $rrdstep, -- 'DS:virus:ABSOLUTE:'.($rrdstep*2).':0:U', -- 'DS:spam:ABSOLUTE:'.($rrdstep*2).':0:U', -- "RRA:AVERAGE:0.5:$day_steps:$realrows", # day -- "RRA:AVERAGE:0.5:$week_steps:$realrows", # week -- "RRA:AVERAGE:0.5:$month_steps:$realrows", # month -- "RRA:AVERAGE:0.5:$year_steps:$realrows", # year -- "RRA:MAX:0.5:$day_steps:$realrows", # day -- "RRA:MAX:0.5:$week_steps:$realrows", # week -- "RRA:MAX:0.5:$month_steps:$realrows", # month -- "RRA:MAX:0.5:$year_steps:$realrows", # year -- ); -- } -- elsif(-f $rrd_virus and ! defined $rrd_virus) { -- $this_minute = RRDs::last($rrd_virus) + $rrdstep; -- } -+ my $m = shift; -+ my $rows = $xpoints/$points_per_sample; -+ my $realrows = int($rows*1.1); # ensure that the full range is covered -+ my $day_steps = int(3600*24 / ($rrdstep*$rows)); -+ # use multiples, otherwise rrdtool could choose the wrong RRA -+ my $week_steps = $day_steps*7; -+ my $month_steps = $week_steps*5; -+ my $year_steps = $month_steps*12; -+ -+ # mail rrd -+ if(! -f $rrd and ! $opt{'no-mail-rrd'}) { -+ RRDs::create($rrd, '--start', $m, '--step', $rrdstep, -+ 'DS:sent:ABSOLUTE:'.($rrdstep*2).':0:U', -+ 'DS:recv:ABSOLUTE:'.($rrdstep*2).':0:U', -+ 'DS:bounced:ABSOLUTE:'.($rrdstep*2).':0:U', -+ 'DS:rejected:ABSOLUTE:'.($rrdstep*2).':0:U', -+ "RRA:AVERAGE:0.5:$day_steps:$realrows", # day -+ "RRA:AVERAGE:0.5:$week_steps:$realrows", # week -+ "RRA:AVERAGE:0.5:$month_steps:$realrows", # month -+ "RRA:AVERAGE:0.5:$year_steps:$realrows", # year -+ "RRA:MAX:0.5:$day_steps:$realrows", # day -+ "RRA:MAX:0.5:$week_steps:$realrows", # week -+ "RRA:MAX:0.5:$month_steps:$realrows", # month -+ "RRA:MAX:0.5:$year_steps:$realrows", # year -+ ); -+ $this_minute = $m; -+ } -+ elsif(-f $rrd) { -+ $this_minute = RRDs::last($rrd) + $rrdstep; -+ } -+ -+ # virus rrd -+ if(! -f $rrd_virus and ! $opt{'no-virus-rrd'}) { -+ RRDs::create($rrd_virus, '--start', $m, '--step', $rrdstep, -+ 'DS:virus:ABSOLUTE:'.($rrdstep*2).':0:U', -+ 'DS:spam:ABSOLUTE:'.($rrdstep*2).':0:U', -+ "RRA:AVERAGE:0.5:$day_steps:$realrows", # day -+ "RRA:AVERAGE:0.5:$week_steps:$realrows", # week -+ "RRA:AVERAGE:0.5:$month_steps:$realrows", # month -+ "RRA:AVERAGE:0.5:$year_steps:$realrows", # year -+ "RRA:MAX:0.5:$day_steps:$realrows", # day -+ "RRA:MAX:0.5:$week_steps:$realrows", # week -+ "RRA:MAX:0.5:$month_steps:$realrows", # month -+ "RRA:MAX:0.5:$year_steps:$realrows", # year -+ ); -+ } -+ elsif(-f $rrd_virus and ! defined $rrd_virus) { -+ $this_minute = RRDs::last($rrd_virus) + $rrdstep; -+ } -+ # greylist rrd -+ if(! -f $rrd_greylist and ! $opt{'no-greylist-rrd'}) { -+ RRDs::create($rrd_greylist, '--start', $m, '--step', $rrdstep, -+ 'DS:greylisted:ABSOLUTE:'.($rrdstep*2).':0:U', -+ 'DS:delayed:ABSOLUTE:'.($rrdstep*2).':0:U', -+ "RRA:AVERAGE:0.5:$day_steps:$realrows", # day -+ "RRA:AVERAGE:0.5:$week_steps:$realrows", # week -+ "RRA:AVERAGE:0.5:$month_steps:$realrows", # month -+ "RRA:AVERAGE:0.5:$year_steps:$realrows", # year -+ "RRA:MAX:0.5:$day_steps:$realrows", # day -+ "RRA:MAX:0.5:$week_steps:$realrows", # week -+ "RRA:MAX:0.5:$month_steps:$realrows", # month -+ "RRA:MAX:0.5:$year_steps:$realrows", # year -+ ); -+ $this_minute = $m; -+ } -+ elsif(-f $rrd_greylist and ! defined $rrd_greylist) { -+ $this_minute = RRDs::last($rrd_greylist) + $rrdstep; -+ } - -- $rrd_inited=1; -+ $rrd_inited=1; - } - - sub process_line($) - { -- my $sl = shift; -- my $time = $sl->[0]; -- my $prog = $sl->[2]; -- my $text = $sl->[4]; -- -- if($prog =~ /^postfix\/(.*)/) { -- my $prog = $1; -- if($prog eq 'smtp') { -- if($text =~ /\bstatus=sent\b/) { -- return if $opt{'ignore-localhost'} and -- $text =~ /\brelay=[^\s\[]*\[127\.0\.0\.1\]/; -- if(defined $opt{'ignore-host-re'}) { -- for my $ih (@{$opt{'ignore-host-re'}}) { -- warn "MATCH! $text\n" if $text =~ $ih; -- return if $text =~ $ih; -- } -- } -- event($time, 'sent'); -- } -- elsif($text =~ /\bstatus=bounced\b/) { -- event($time, 'bounced'); -- } -- } -- elsif($prog eq 'local') { -- if($text =~ /\bstatus=bounced\b/) { -- event($time, 'bounced'); -- } -- } -- elsif($prog eq 'smtpd') { -- if($text =~ /^[0-9A-Z]+: client=(\S+)/) { -- my $client = $1; -- return if $opt{'ignore-localhost'} and -- $client =~ /\[127\.0\.0\.1\]$/; -- return if $opt{'ignore-host'} and -- $client =~ /$opt{'ignore-host'}/oi; -- event($time, 'received'); -- } -- elsif($opt{'virbl-is-virus'} and $text =~ /^(?:[0-9A-Z]+: |NOQUEUE: )?reject: .*: 554.* blocked using virbl.dnsbl.bit.nl/) { -- event($time, 'virus'); -- } -- elsif($opt{'rbl-is-spam'} and $text =~ /^(?:[0-9A-Z]+: |NOQUEUE: )?reject: .*: 554.* blocked using/) { -- event($time, 'spam'); -- } -- elsif($text =~ /^(?:[0-9A-Z]+: |NOQUEUE: )?reject: /) { -- event($time, 'rejected'); -- } -- elsif($text =~ /^(?:[0-9A-Z]+: |NOQUEUE: )?milter-reject: /) { -- if($text =~ /Blocked by SpamAssassin/) { -- event($time, 'spam'); -- } -- else { -- event($time, 'rejected'); -- } -- } -- } -- elsif($prog eq 'error') { -- if($text =~ /\bstatus=bounced\b/) { -- event($time, 'bounced'); -- } -- } -- elsif($prog eq 'cleanup') { -- if($text =~ /^[0-9A-Z]+: (?:reject|discard): /) { -- event($time, 'rejected'); -- } -- } -- } -- elsif($prog eq 'sendmail' or $prog eq 'sm-mta') { -- if($text =~ /\bmailer=local\b/ ) { -- event($time, 'received'); -- } -+ my $sl = shift; -+ my $time = $sl->[0]; -+ my $prog = $sl->[2]; -+ my $text = $sl->[4]; -+ -+ if($prog =~ /^postfix\/(.*)/) { -+ my $prog = $1; -+ if($prog eq 'smtp') { -+ if($text =~ /\bstatus=sent\b/) { -+ return if $opt{'ignore-localhost'} and -+ $text =~ /\brelay=[^\s\[]*\[127\.0\.0\.1\]/; -+ if(defined $opt{'ignore-host-re'}) { -+ for my $ih (@{$opt{'ignore-host-re'}}) { -+ warn "MATCH! $text\n" if $text =~ $ih; -+ return if $text =~ $ih; -+ } -+ } -+ event($time, 'sent'); -+ } -+ elsif($text =~ /\bstatus=bounced\b/) { -+ event($time, 'bounced'); -+ } -+ } -+ elsif($prog eq 'local') { -+ if($text =~ /\bstatus=bounced\b/) { -+ event($time, 'bounced'); -+ } -+ } -+ elsif($prog eq 'smtpd' || $prog eq 'postscreen') { -+ if($text =~ /^(?:[\dA-F]+|[\dB-DF-HJ-NP-TV-Zb-df-hj-np-tv-z]+): client=(\S+)/) { -+ my $client = $1; -+ return if $opt{'ignore-localhost'} and -+ $client =~ /\[127\.0\.0\.1\]$/; -+ return if $opt{'ignore-host'} and -+ $client =~ /$opt{'ignore-host'}/oi; -+ event($time, 'received'); -+ } -+ elsif($opt{'virbl-is-virus'} and $text =~ /^(?:[\dA-F]+: |[\dB-DF-HJ-NP-TV-Zb-df-hj-np-tv-z]+: |NOQUEUE: )?reject: .*: 554.* blocked using virbl.dnsbl.bit.nl/) { -+ event($time, 'virus'); -+ } -+ elsif($opt{'rbl-is-spam'} and $text =~ /^(?:[\dA-F]+: |[\dB-DF-HJ-NP-TV-Zb-df-hj-np-tv-z]+: |NOQUEUE: )?reject: .*: 554.* blocked using/) { -+ event($time, 'spam'); -+ } -+ elsif($text =~ /Greylisted/) { -+ event($time, 'greylisted'); -+ } -+ elsif($text =~ /^(?:[\dA-F]+: |[\dB-DF-HJ-NP-TV-Zb-df-hj-np-tv-z]+: |NOQUEUE: )?reject: /) { -+ event($time, 'rejected'); -+ } -+ elsif($text =~ /^(?:[\dA-F]+: |[\dB-DF-HJ-NP-TV-Zb-df-hj-np-tv-z]+: |NOQUEUE: )?milter-reject: /) { -+ if($text =~ /Blocked by SpamAssassin/) { -+ event($time, 'spam'); -+ } -+ else { -+ event($time, 'rejected'); -+ } -+ } -+ } -+ elsif($prog eq 'error') { -+ if($text =~ /\bstatus=bounced\b/) { -+ event($time, 'bounced'); -+ } -+ } -+ elsif($prog eq 'cleanup') { -+ if($text =~ /(?:[\dA-F]+|[\dB-DF-HJ-NP-TV-Zb-df-hj-np-tv-z]+): (?:reject|discard): /) { -+ event($time, 'rejected'); -+ } -+ } -+ } -+ elsif($prog eq 'sendmail' or $prog eq 'sm-mta') { -+ if($text =~ /\bmailer=local\b/ ) { -+ event($time, 'received'); -+ } - elsif($text =~ /\bmailer=relay\b/) { - event($time, 'received'); - } -- elsif($text =~ /\bstat=Sent\b/ ) { -- event($time, 'sent'); -- } -+ elsif($text =~ /\bstat=Sent\b/ ) { -+ event($time, 'sent'); -+ } - elsif($text =~ /\bmailer=esmtp\b/ ) { - event($time, 'sent'); - } -- elsif($text =~ /\bruleset=check_XS4ALL\b/ ) { -- event($time, 'rejected'); -- } -- elsif($text =~ /\blost input channel\b/ ) { -- event($time, 'rejected'); -- } -- elsif($text =~ /\bruleset=check_rcpt\b/ ) { -- event($time, 'rejected'); -- } -+ elsif($text =~ /\bruleset=check_XS4ALL\b/ ) { -+ event($time, 'rejected'); -+ } -+ elsif($text =~ /\blost input channel\b/ ) { -+ event($time, 'rejected'); -+ } -+ elsif($text =~ /\bruleset=check_rcpt\b/ ) { -+ event($time, 'rejected'); -+ } - elsif($text =~ /\bstat=virus\b/ ) { - event($time, 'virus'); - } -- elsif($text =~ /\bruleset=check_relay\b/ ) { -- if (($opt{'virbl-is-virus'}) and ($text =~ /\bivirbl\b/ )) { -- event($time, 'virus'); -- } elsif ($opt{'rbl-is-spam'}) { -- event($time, 'spam'); -- } else { -- event($time, 'rejected'); -- } -- } -- elsif($text =~ /\bsender blocked\b/ ) { -- event($time, 'rejected'); -- } -- elsif($text =~ /\bsender denied\b/ ) { -- event($time, 'rejected'); -- } -- elsif($text =~ /\brecipient denied\b/ ) { -- event($time, 'rejected'); -- } -- elsif($text =~ /\brecipient unknown\b/ ) { -- event($time, 'rejected'); -- } -- elsif($text =~ /\bUser unknown$/i ) { -- event($time, 'bounced'); -- } -- elsif($text =~ /\bMilter:.*\breject=55/ ) { -- event($time, 'rejected'); -- } -- } -- elsif($prog eq 'exim') { -- if($text =~ /^[0-9a-zA-Z]{6}-[0-9a-zA-Z]{6}-[0-9a-zA-Z]{2} <= \S+/) { -- event($time, 'received'); -- } -- elsif($text =~ /^[0-9a-zA-Z]{6}-[0-9a-zA-Z]{6}-[0-9a-zA-Z]{2} => \S+/) { -- event($time, 'sent'); -- } -- elsif($text =~ / rejected because \S+ is in a black list at \S+/) { -- if($opt{'rbl-is-spam'}) { -- event($time, 'spam'); -- } else { -- event($time, 'rejected'); -- } -- } -- elsif($text =~ / rejected RCPT \S+: (Sender verify failed|Unknown user)/) { -- event($time, 'rejected'); -- } -- } -- elsif($prog eq 'amavis' || $prog eq 'amavisd') { -- if( $text =~ /^\([\w-]+\) (Passed|Blocked) SPAM(?:MY)?\b/) { -- if($text !~ /\btag2=/) { # ignore new per-recipient log entry (2.2.0) -- event($time, 'spam'); # since amavisd-new-2004xxxx -- } -- } -- elsif($text =~ /^\([\w-]+\) (Passed|Not-Delivered)\b.*\bquarantine spam/) { -- event($time, 'spam'); # amavisd-new-20030616 and earlier -- } -- elsif($text =~ /^\([\w-]+\) (Passed |Blocked )?INFECTED\b/) { -- if($text !~ /\btag2=/) { -- event($time, 'virus');# Passed|Blocked inserted since 2004xxxx -- } -- } -- elsif($text =~ /^\([\w-]+\) (Passed |Blocked )?BANNED\b/) { -- if($text !~ /\btag2=/) { -- event($time, 'virus'); -- } -- } -- elsif($text =~ /^Virus found\b/) { -- event($time, 'virus');# AMaViS 0.3.12 and amavisd-0.1 -- } --# elsif($text =~ /^\([\w-]+\) Passed|Blocked BAD-HEADER\b/) { --# event($time, 'badh'); --# } -- } -- elsif($prog eq 'vagatefwd') { -- # Vexira antivirus (old) -- if($text =~ /^VIRUS/) { -- event($time, 'virus'); -- } -- } -- elsif($prog eq 'hook') { -- # Vexira antivirus -- if($text =~ /^\*+ Virus\b/) { -- event($time, 'virus'); -- } -- # Vexira antispam -- elsif($text =~ /\bcontains spam\b/) { -- event($time, 'spam'); -- } -- } -- elsif($prog eq 'avgatefwd' or $prog eq 'avmailgate.bin') { -- # AntiVir MailGate -- if($text =~ /^Alert!/) { -- event($time, 'virus'); -- } -- elsif($text =~ /blocked\.$/) { -- event($time, 'virus'); -- } -- } -- elsif($prog eq 'avcheck') { -- # avcheck -- if($text =~ /^infected/) { -- event($time, 'virus'); -- } -- } -- elsif($prog eq 'spamd') { -- if($text =~ /^(?:spamd: )?identified spam/) { -- event($time, 'spam'); -- } -- # ClamAV SpamAssassin-plugin -- elsif($text =~ /(?:result: )?CLAMAV/) { -- event($time, 'virus'); -- } -- } -- elsif($prog eq 'dspam') { -- if($text =~ /spam detected from/) { -- event($time, 'spam'); -- } -- } -- elsif($prog eq 'spamproxyd' or $prog eq 'spampd') { -- if($text =~ /^\s*SPAM/ or $text =~ /^identified spam/) { -- event($time, 'spam'); -- } -- } -- elsif($prog eq 'drweb-postfix') { -- # DrWeb -- if($text =~ /infected/) { -- event($time, 'virus'); -- } -- } -- elsif($prog eq 'BlackHole') { -- if($text =~ /Virus/) { -- event($time, 'virus'); -- } -- if($text =~ /(?:RBL|Razor|Spam)/) { -- event($time, 'spam'); -- } -- } -- elsif($prog eq 'MailScanner') { -- if($text =~ /(Virus Scanning: Found)/ ) { -- event($time, 'virus'); -- } -- elsif($text =~ /Bounce to/ ) { -- event($time, 'bounced'); -- } -- elsif($text =~ /^Spam Checks: Found ([0-9]+) spam messages/) { -- my $cnt = $1; -- for (my $i=0; $i<$cnt; $i++) { -- event($time, 'spam'); -- } -- } -- } -- elsif($prog eq 'clamsmtpd') { -- if($text =~ /status=VIRUS/) { -- event($time, 'virus'); -- } -- } -- elsif($prog eq 'clamav-milter') { -- if($text =~ /Intercepted/) { -- event($time, 'virus'); -- } -- } -- # uncommment for clamassassin: -- #elsif($prog eq 'clamd') { -- # if($text =~ /^stream: .* FOUND$/) { -- # event($time, 'virus'); -- # } -- #} -- elsif ($prog eq 'smtp-vilter') { -- if ($text =~ /clamd: found/) { -- event($time, 'virus'); -- } -- } -- elsif($prog eq 'avmilter') { -- # AntiVir Milter -- if($text =~ /^Alert!/) { -- event($time, 'virus'); -- } -- elsif($text =~ /blocked\.$/) { -- event($time, 'virus'); -- } -- } -- elsif($prog eq 'bogofilter') { -- if($text =~ /Spam/) { -- event($time, 'spam'); -- } -- } -- elsif($prog eq 'filter-module') { -- if($text =~ /\bspam_status\=(?:yes|spam)/) { -- event($time, 'spam'); -- } -- } -- elsif($prog eq 'sta_scanner') { -- if($text =~ /^[0-9A-F]+: virus/) { -- event($time, 'virus'); -- } -- } -+ elsif($text =~ /\bruleset=check_relay\b/ ) { -+ if (($opt{'virbl-is-virus'}) and ($text =~ /\bivirbl\b/ )) { -+ event($time, 'virus'); -+ } elsif ($opt{'rbl-is-spam'}) { -+ event($time, 'spam'); -+ } else { -+ event($time, 'rejected'); -+ } -+ } -+ elsif($text =~ /\bsender blocked\b/ ) { -+ event($time, 'rejected'); -+ } -+ elsif($text =~ /\bsender denied\b/ ) { -+ event($time, 'rejected'); -+ } -+ elsif($text =~ /\brecipient denied\b/ ) { -+ event($time, 'rejected'); -+ } -+ elsif($text =~ /\brecipient unknown\b/ ) { -+ event($time, 'rejected'); -+ } -+ elsif($text =~ /\bUser unknown$/i ) { -+ event($time, 'bounced'); -+ } -+ elsif($text =~ /\bMilter:.*\breject=55/ ) { -+ event($time, 'rejected'); -+ } -+ } -+ elsif($prog eq 'exim') { -+ if($text =~ /^[0-9a-zA-Z]{6}-[0-9a-zA-Z]{6}-[0-9a-zA-Z]{2} <= \S+/) { -+ event($time, 'received'); -+ } -+ elsif($text =~ /^[0-9a-zA-Z]{6}-[0-9a-zA-Z]{6}-[0-9a-zA-Z]{2} => \S+/) { -+ event($time, 'sent'); -+ } -+ elsif($text =~ / rejected because \S+ is in a black list at \S+/) { -+ if($opt{'rbl-is-spam'}) { -+ event($time, 'spam'); -+ } else { -+ event($time, 'rejected'); -+ } -+ } -+ elsif($text =~ / rejected RCPT \S+: (Sender verify failed|Unknown user)/) { -+ event($time, 'rejected'); -+ } -+ } -+ elsif($prog eq 'amavis' || $prog eq 'amavisd') { -+ if( $text =~ /^\([\w-]+\) (Passed|Blocked) SPAM(?:MY)?\b/) { -+ if($text !~ /\btag2=/) { # ignore new per-recipient log entry (2.2.0) -+ event($time, 'spam'); # since amavisd-new-2004xxxx -+ } -+ } -+ elsif($text =~ /^\([\w-]+\) (Passed|Not-Delivered)\b.*\bquarantine spam/) { -+ event($time, 'spam'); # amavisd-new-20030616 and earlier -+ } -+ elsif($text =~ /^\([\w-]+\) (Passed |Blocked )?INFECTED\b/) { -+ if($text !~ /\btag2=/) { -+ event($time, 'virus');# Passed|Blocked inserted since 2004xxxx -+ } -+ } -+ elsif($text =~ /^\([\w-]+\) (Passed |Blocked )?BANNED\b/) { -+ if($text !~ /\btag2=/) { -+ event($time, 'virus'); -+ } -+ } -+ elsif($text =~ /^Virus found\b/) { -+ event($time, 'virus');# AMaViS 0.3.12 and amavisd-0.1 -+ } -+# elsif($text =~ /^\([\w-]+\) Passed|Blocked BAD-HEADER\b/) { -+# event($time, 'badh'); -+# } -+ } -+ elsif($prog eq 'vagatefwd') { -+ # Vexira antivirus (old) -+ if($text =~ /^VIRUS/) { -+ event($time, 'virus'); -+ } -+ } -+ elsif($prog eq 'hook') { -+ # Vexira antivirus -+ if($text =~ /^\*+ Virus\b/) { -+ event($time, 'virus'); -+ } -+ # Vexira antispam -+ elsif($text =~ /\bcontains spam\b/) { -+ event($time, 'spam'); -+ } -+ } -+ elsif($prog eq 'avgatefwd' or $prog eq 'avmailgate.bin') { -+ # AntiVir MailGate -+ if($text =~ /^Alert!/) { -+ event($time, 'virus'); -+ } -+ elsif($text =~ /blocked\.$/) { -+ event($time, 'virus'); -+ } -+ } -+ elsif($prog eq 'avcheck') { -+ # avcheck -+ if($text =~ /^infected/) { -+ event($time, 'virus'); -+ } -+ } -+ elsif($prog eq 'spamd') { -+ if($text =~ /^(?:spamd: )?identified spam/) { -+ event($time, 'spam'); -+ } -+ # ClamAV SpamAssassin-plugin -+ elsif($text =~ /(?:result: )?CLAMAV/) { -+ event($time, 'virus'); -+ } -+ } -+ elsif($prog eq 'dspam') { -+ if($text =~ /spam detected from/) { -+ event($time, 'spam'); -+ } -+ elsif($text =~ /infected message from/) { -+ event($time, 'virus'); -+ } -+ } -+ elsif($prog eq 'spamproxyd' or $prog eq 'spampd') { -+ if($text =~ /^\s*SPAM/ or $text =~ /^identified spam/) { -+ event($time, 'spam'); -+ } -+ } -+ elsif($prog eq 'drweb-postfix') { -+ # DrWeb -+ if($text =~ /infected/) { -+ event($time, 'virus'); -+ } -+ } -+ elsif($prog eq 'BlackHole') { -+ if($text =~ /Virus/) { -+ event($time, 'virus'); -+ } -+ if($text =~ /(?:RBL|Razor|Spam)/) { -+ event($time, 'spam'); -+ } -+ } -+ elsif($prog eq 'MailScanner') { -+ if($text =~ /(Virus Scanning: Found)/ ) { -+ event($time, 'virus'); -+ } -+ elsif($text =~ /Bounce to/ ) { -+ event($time, 'bounced'); -+ } -+ elsif($text =~ /^Spam Checks: Found ([0-9]+) spam messages/) { -+ my $cnt = $1; -+ for (my $i=0; $i<$cnt; $i++) { -+ event($time, 'spam'); -+ } -+ } -+ } -+ elsif($prog eq 'clamsmtpd') { -+ if($text =~ /status=VIRUS/) { -+ event($time, 'virus'); -+ } -+ } -+ elsif($prog eq 'clamav-milter') { -+ if($text =~ /Intercepted/) { -+ event($time, 'virus'); -+ } -+ elsif($text =~ /Message.*infected by/) { -+ event($time, 'virus'); -+ } -+ } -+ # uncommment for clamassassin: -+ #elsif($prog eq 'clamd') { -+ # if($text =~ /^stream: .* FOUND$/) { -+ # event($time, 'virus'); -+ # } -+ #} -+ elsif ($prog eq 'smtp-vilter') { -+ if ($text =~ /clamd: found/) { -+ event($time, 'virus'); -+ } -+ } -+ elsif($prog eq 'avmilter') { -+ # AntiVir Milter -+ if($text =~ /^Alert!/) { -+ event($time, 'virus'); -+ } -+ elsif($text =~ /blocked\.$/) { -+ event($time, 'virus'); -+ } -+ } -+ elsif($prog eq 'bogofilter') { -+ if($text =~ /Spam/) { -+ event($time, 'spam'); -+ } -+ } -+ elsif($prog eq 'filter-module') { -+ if($text =~ /\bspam_status\=(?:yes|spam)/) { -+ event($time, 'spam'); -+ } -+ } -+ elsif($prog eq 'sta_scanner') { -+ if($text =~ /^[0-9A-F]+: virus/) { -+ event($time, 'virus'); -+ } -+ } -+ elsif($prog eq 'postgrey') { -+ # Old versions (up to 1.27) -+ if($text =~ /delayed [0-9]+ seconds: client/) { -+ event($time, 'delayed'); -+ } -+ # New versions (from 1.28) -+ if($text =~ /delay=[0-9]+/) { -+ event($time, 'delayed'); -+ } -+ } -+ elsif($prog eq 'grossd') { -+ if($text =~ /a\=greylist/) { -+ event($time, 'greylisted'); -+ } -+ } - } - - sub event($$) - { -- my ($t, $type) = @_; -- update($t) and $sum{$type}++; -+ my ($t, $type) = @_; -+ update($t) and $sum{$type}++; - } - - # returns 1 if $sum should be updated - sub update($) - { -- my $t = shift; -- my $m = $t - $t%$rrdstep; -- init_rrd($m) unless $rrd_inited; -- return 1 if $m == $this_minute; -- return 0 if $m < $this_minute; -- -- print "update $this_minute:$sum{sent}:$sum{received}:$sum{bounced}:$sum{rejected}:$sum{virus}:$sum{spam}\n" if $opt{verbose}; -- RRDs::update $rrd, "$this_minute:$sum{sent}:$sum{received}:$sum{bounced}:$sum{rejected}" unless $opt{'only-virus-rrd'}; -- RRDs::update $rrd_virus, "$this_minute:$sum{virus}:$sum{spam}" unless $opt{'only-mail-rrd'}; -- if($m > $this_minute+$rrdstep) { -- for(my $sm=$this_minute+$rrdstep;$sm<$m;$sm+=$rrdstep) { -- print "update $sm:0:0:0:0:0:0 (SKIP)\n" if $opt{verbose}; -- RRDs::update $rrd, "$sm:0:0:0:0" unless $opt{'only-virus-rrd'}; -- RRDs::update $rrd_virus, "$sm:0:0" unless $opt{'only-mail-rrd'}; -- } -- } -- $this_minute = $m; -- $sum{sent}=0; -- $sum{received}=0; -- $sum{bounced}=0; -- $sum{rejected}=0; -- $sum{virus}=0; -- $sum{spam}=0; -- return 1; -+ my $t = shift; -+ my $m = $t - $t%$rrdstep; -+ init_rrd($m) unless $rrd_inited; -+ return 1 if $m == $this_minute; -+ return 0 if $m < $this_minute; -+ -+ print "update $this_minute:$sum{sent}:$sum{received}:$sum{bounced}:$sum{rejected}:$sum{virus}:$sum{spam}:$sum{greylisted}:$sum{delayed}\n" if $opt{verbose}; -+ RRDs::update $rrd, "$this_minute:$sum{sent}:$sum{received}:$sum{bounced}:$sum{rejected}" unless $opt{'no-mail-rrd'}; -+ RRDs::update $rrd_virus, "$this_minute:$sum{virus}:$sum{spam}" unless $opt{'no-virus-rrd'}; -+ RRDs::update $rrd_greylist, "$this_minute:$sum{greylisted}:$sum{delayed}" unless $opt{'no-greylist-rrd'}; -+ if($m > $this_minute+$rrdstep) { -+ for(my $sm=$this_minute+$rrdstep;$sm<$m;$sm+=$rrdstep) { -+ print "update $sm:0:0:0:0:0:0:0:0 (SKIP)\n" if $opt{verbose}; -+ RRDs::update $rrd, "$sm:0:0:0:0" unless $opt{'no-mail-rrd'}; -+ RRDs::update $rrd_virus, "$sm:0:0" unless $opt{'no-virus-rrd'}; -+ RRDs::update $rrd_greylist, "$sm:0:0" unless $opt{'no-greylist-rrd'}; -+ } -+ } -+ $this_minute = $m; -+ $sum{sent}=0; -+ $sum{received}=0; -+ $sum{bounced}=0; -+ $sum{rejected}=0; -+ $sum{virus}=0; -+ $sum{spam}=0; -+ $sum{greylisted}=0; -+ $sum{delayed}=0; -+ return 1; - } - - main; -@@ -919,8 +993,9 @@ B [I...] - --daemon-log=FILE write verbose-log to FILE instead of /var/log/mailgraph.log - --ignore-localhost ignore mail to/from localhost (used for virus scanner) - --ignore-host=HOST ignore mail to/from HOST regexp (used for virus scanner) -- --only-mail-rrd update only the mail rrd -- --only-virus-rrd update only the virus rrd -+ --no-mail-rrd do not update mail rrd -+ --no-virus-rrd do not update virus rrd -+ --no-greylist-rrd do not update greylist rrd - --rrd-name=NAME use NAME.rrd and NAME_virus.rrd for the rrd files - --rbl-is-spam count rbl rejects as spam - --virbl-is-virus count virbl rejects as viruses -@@ -940,6 +1015,10 @@ The following types can be given to --lo - - Traditional "syslog" (default) - -+=item rsyslog -+ -+High precision format "rsyslog" -+ - =item metalog - - Metalog (see http://metalog.sourceforge.net/) -@@ -950,6 +1029,7 @@ Metalog (see http://metalog.sourceforge. - - Copyright (c) 2000-2007 by ETH Zurich - Copyright (c) 2000-2007 by David Schweikert -+Copyright (c) 2018 by M.D. Klapwijk - - =head1 LICENSE - -@@ -973,4 +1053,4 @@ Sdavid@schweikert - - =cut - --# vi: sw=8 -+# vi: sw=8 -\ No newline at end of file -- cgit v1.2.3