perltidy -b watch summarize show_message log2sql
This commit is contained in:
parent
58aab2ad20
commit
cd23266105
246
log/log2sql
246
log/log2sql
@ -26,7 +26,7 @@ foreach my $file ( @logfiles ) {
|
||||
my ($fid, $offset) = check_logfile($file);
|
||||
$fid or next;
|
||||
parse_logfile($file, $fid, $offset);
|
||||
};
|
||||
}
|
||||
|
||||
exit;
|
||||
|
||||
@ -47,7 +47,7 @@ sub trim_message {
|
||||
return '' if $mess eq 'TLS setup returning';
|
||||
|
||||
return $mess;
|
||||
};
|
||||
}
|
||||
|
||||
sub get_os_id {
|
||||
my $p0f_string = shift or return;
|
||||
@ -66,15 +66,15 @@ sub get_os_id {
|
||||
my $ref = exec_query('SELECT * FROM os');
|
||||
foreach my $o (@$ref) {
|
||||
$os{$o->{name}} = $o->{id};
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (!defined $os{$p0f_string}) {
|
||||
warn "missing OS for $p0f_string\n";
|
||||
};
|
||||
}
|
||||
|
||||
return $os{$p0f_string};
|
||||
};
|
||||
}
|
||||
|
||||
sub get_plugin_id {
|
||||
my $plugin = shift;
|
||||
@ -84,20 +84,21 @@ sub get_plugin_id {
|
||||
foreach my $p (@$ref) {
|
||||
$plugins{$p->{name}} = $p->{id};
|
||||
$plugins{$p->{id}} = $p->{name};
|
||||
};
|
||||
}
|
||||
$ref = exec_query('SELECT * FROM plugin_aliases');
|
||||
foreach my $pa (@$ref) {
|
||||
$plugins{$pa->{name}} = $pa->{plugin_id};
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (!defined $plugins{$plugin}) {
|
||||
|
||||
#warn Dumper(\%plugins);
|
||||
die "missing DB plugin $plugin\n";
|
||||
};
|
||||
}
|
||||
|
||||
return $plugins{$plugin};
|
||||
};
|
||||
}
|
||||
|
||||
sub get_msg_id {
|
||||
my ($fid, $pid) = @_;
|
||||
@ -105,16 +106,15 @@ sub get_msg_id {
|
||||
return $message_ids{"$fid-$pid"} if $message_ids{"$fid-$pid"};
|
||||
|
||||
#print "searching for message $pid...";
|
||||
my $msgs = exec_query(
|
||||
'SELECT * FROM message WHERE file_id=? AND qp_pid=?',
|
||||
[ $fid, $pid ]
|
||||
);
|
||||
my $msgs = exec_query('SELECT * FROM message WHERE file_id=? AND qp_pid=?',
|
||||
[$fid, $pid]);
|
||||
|
||||
#print scalar @$msgs ? "y\n" : "n\n";
|
||||
if ($msgs->[0]{id}) {
|
||||
$message_ids{"$fid-$pid"} = $msgs->[0]{id};
|
||||
};
|
||||
}
|
||||
return $msgs->[0]{id};
|
||||
};
|
||||
}
|
||||
|
||||
sub create_message {
|
||||
my ($fid, $ts, $pid, $message) = @_;
|
||||
@ -129,9 +129,10 @@ sub create_message {
|
||||
|
||||
if ($host && $host ne 'Unknown') {
|
||||
exec_query("UPDATE message SET hostname=? WHERE id=?", [$host, $id]);
|
||||
};
|
||||
}
|
||||
|
||||
#warn "host updated: $host\n";
|
||||
};
|
||||
}
|
||||
|
||||
sub insert_plugin {
|
||||
my ($msg_id, $plugin, $message) = @_;
|
||||
@ -141,21 +142,24 @@ sub insert_plugin {
|
||||
if ($plugin eq 'ident::geoip') {
|
||||
my ($gip, $distance) = $message =~ /(.*?),\s+([\d]+)\skm/;
|
||||
if ($distance) {
|
||||
exec_query( 'UPDATE message SET distance=? WHERE id=?', [ $distance, $msg_id ] );
|
||||
exec_query('UPDATE message SET distance=? WHERE id=?',
|
||||
[$distance, $msg_id]);
|
||||
$message = $gip;
|
||||
}
|
||||
}
|
||||
elsif ($plugin =~ /^ident::p0f/) {
|
||||
my $os_id = get_os_id($message);
|
||||
if ($os_id) {
|
||||
exec_query( 'UPDATE message SET os_id=? WHERE id=?', [ $os_id, $msg_id ] );
|
||||
exec_query('UPDATE message SET os_id=? WHERE id=?',
|
||||
[$os_id, $msg_id]);
|
||||
$message = 'pass';
|
||||
}
|
||||
}
|
||||
elsif ($plugin eq 'connection_time') {
|
||||
my ($seconds) = $message =~ /\s*([\d\.]+)\s/;
|
||||
if ($seconds) {
|
||||
exec_query( 'UPDATE message SET time=? WHERE id=?', [ $seconds, $msg_id ] );
|
||||
exec_query('UPDATE message SET time=? WHERE id=?',
|
||||
[$seconds, $msg_id]);
|
||||
$message = 'pass';
|
||||
}
|
||||
}
|
||||
@ -163,12 +167,13 @@ sub insert_plugin {
|
||||
my $result = get_score($message);
|
||||
if ($result) {
|
||||
$message = trim_message($message);
|
||||
};
|
||||
}
|
||||
|
||||
exec_query( 'INSERT INTO message_plugin SET msg_id=?, plugin_id=?, result=?, string=?',
|
||||
exec_query(
|
||||
'INSERT INTO message_plugin SET msg_id=?, plugin_id=?, result=?, string=?',
|
||||
[$msg_id, $plugin_id, $result, $message]
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
sub parse_logfile {
|
||||
my $file = shift;
|
||||
@ -213,21 +218,27 @@ sub parse_logfile {
|
||||
}
|
||||
elsif ($type eq 'close') {
|
||||
if ($message eq 'Connection Timed Out') {
|
||||
exec_query('UPDATE message SET result=? WHERE id=?', [ -1, $msg_id ] );
|
||||
};
|
||||
exec_query('UPDATE message SET result=? WHERE id=?',
|
||||
[-1, $msg_id]);
|
||||
}
|
||||
}
|
||||
elsif ($type eq 'connect') { }
|
||||
elsif ($type eq 'dispatch') {
|
||||
if (substr($message, 0, 21) eq 'dispatching MAIL FROM') {
|
||||
my ($from) = $message =~ /<(.*?)>/;
|
||||
exec_query('UPDATE message SET mail_from=? WHERE id=?', [ $from, $msg_id ] );
|
||||
exec_query('UPDATE message SET mail_from=? WHERE id=?',
|
||||
[$from, $msg_id]);
|
||||
}
|
||||
elsif (substr($message, 0, 19) eq 'dispatching RCPT TO') {
|
||||
my ($to) = $message =~ /<(.*?)>/;
|
||||
exec_query('UPDATE message SET rcpt_to=? WHERE id=? AND rcpt_to IS NULL', [ $to, $msg_id ] );
|
||||
exec_query(
|
||||
'UPDATE message SET rcpt_to=? WHERE id=? AND rcpt_to IS NULL',
|
||||
[$to, $msg_id]
|
||||
);
|
||||
}
|
||||
elsif ($message =~ m/dispatching (EHLO|HELO) (.*)/) {
|
||||
exec_query('UPDATE message SET helo=? WHERE id=?', [ $2, $msg_id ] );
|
||||
exec_query('UPDATE message SET helo=? WHERE id=?',
|
||||
[$2, $msg_id]);
|
||||
}
|
||||
elsif ($message eq 'dispatching DATA') { }
|
||||
elsif ($message eq 'dispatching QUIT') { }
|
||||
@ -236,15 +247,15 @@ sub parse_logfile {
|
||||
else {
|
||||
# anything here is likely an unrecognized command
|
||||
#print "$message\n";
|
||||
};
|
||||
}
|
||||
}
|
||||
else {
|
||||
print "$type $pid $hook $plugin $message\n";
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
close $F;
|
||||
};
|
||||
}
|
||||
|
||||
sub check_logfile {
|
||||
my $file = shift;
|
||||
@ -258,38 +269,28 @@ sub check_logfile {
|
||||
|
||||
#warn "check if file $file is in the DB as 'current'\n";
|
||||
if ($file =~ /^\@/) {
|
||||
$exists = exec_query(
|
||||
'SELECT * FROM log WHERE inode=? AND name=?',
|
||||
[ $inode, 'current' ]
|
||||
);
|
||||
$exists = exec_query('SELECT * FROM log WHERE inode=? AND name=?',
|
||||
[$inode, 'current']);
|
||||
if (@$exists) {
|
||||
print "Updating current -> $file\n";
|
||||
exec_query(
|
||||
'UPDATE log SET name=? WHERE inode=? AND name=?',
|
||||
[ $file, $inode, 'current' ]
|
||||
);
|
||||
exec_query('UPDATE log SET name=? WHERE inode=? AND name=?',
|
||||
[$file, $inode, 'current']);
|
||||
return ($exists->[0]{id}, $exists->[0]{size}); # continue parsing
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if ($file eq 'current') {
|
||||
$exists = exec_query(
|
||||
'SELECT * FROM log WHERE inode=? AND name=?',
|
||||
[ $inode, $file ]
|
||||
);
|
||||
$exists = exec_query('SELECT * FROM log WHERE inode=? AND name=?',
|
||||
[$inode, $file]);
|
||||
if (@$exists) {
|
||||
exec_query(
|
||||
'UPDATE log SET size=? WHERE inode=? AND name=?',
|
||||
[ $size, $inode, 'current' ]
|
||||
);
|
||||
exec_query('UPDATE log SET size=? WHERE inode=? AND name=?',
|
||||
[$size, $inode, 'current']);
|
||||
return ($exists->[0]{id}, $exists->[0]{size}); # continue parsing
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
$exists = exec_query(
|
||||
'SELECT * FROM log WHERE name=? AND size=?',
|
||||
[ $file, $size ]
|
||||
);
|
||||
$exists =
|
||||
exec_query('SELECT * FROM log WHERE name=? AND size=?', [$file, $size]);
|
||||
return if @$exists; # log file hasn't changed, ignore it
|
||||
#print Dumper($exists);
|
||||
|
||||
@ -300,14 +301,14 @@ sub check_logfile {
|
||||
);
|
||||
print "new file id: $id\n";
|
||||
return ($id);
|
||||
};
|
||||
}
|
||||
|
||||
sub get_log_dir {
|
||||
|
||||
if (-d "log/main") {
|
||||
my $wd = Cwd::cwd();
|
||||
return "$wd/log/main";
|
||||
};
|
||||
}
|
||||
|
||||
foreach my $user (qw/ qpsmtpd smtpd /) {
|
||||
|
||||
@ -315,13 +316,13 @@ sub get_log_dir {
|
||||
|
||||
if (-d "$homedir/log") {
|
||||
return "$homedir/log/main";
|
||||
};
|
||||
}
|
||||
if (-d "$homedir/smtpd/log") {
|
||||
return "$homedir/smtpd/log/main";
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
sub get_logfiles {
|
||||
my $dir = shift;
|
||||
@ -333,13 +334,13 @@ sub get_logfiles {
|
||||
next if !-f "$dir/$f"; # ignore anything that's not a file
|
||||
if ($f =~ /^\@.*s$/) {
|
||||
push @files, $f;
|
||||
};
|
||||
}
|
||||
}
|
||||
push @files, "current"; # always have this one last
|
||||
|
||||
closedir $D;
|
||||
return @files;
|
||||
};
|
||||
}
|
||||
|
||||
sub parse_line {
|
||||
my $line = shift;
|
||||
@ -348,40 +349,65 @@ sub parse_line {
|
||||
|
||||
# lines seen many times per connection
|
||||
return parse_line_plugin($line) if substr($message, 0, 1) eq '(';
|
||||
return ( 'dispatch', $pid, undef, undef, $message ) if substr($message, 0, 12) eq 'dispatching ';
|
||||
return ( 'queue', $pid, undef, undef, $message ) if substr($message, 0, 11) eq '250 Queued!';
|
||||
return ( 'response', $pid, undef, undef, $message ) if $message =~ /^[2|3]\d\d/;
|
||||
return ('dispatch', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 12) eq 'dispatching ';
|
||||
return ('queue', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 11) eq '250 Queued!';
|
||||
return ('response', $pid, undef, undef, $message)
|
||||
if $message =~ /^[2|3]\d\d/;
|
||||
|
||||
# lines seen about once per connection
|
||||
return ( 'init', $pid, undef, undef, $message ) if substr($message, 0, 19) eq 'Accepted connection';
|
||||
return ( 'connect', $pid, undef, undef, substr( $message, 16) ) if substr($message, 0, 15) eq 'Connection from';
|
||||
return ( 'connect', $pid, undef, undef, substr( $message, 16) ) if substr($message, 0, 8) eq 'connect ';
|
||||
return ( 'close', $pid, undef, undef, $message ) if substr($message, 0, 6) eq 'close ';
|
||||
return ( 'close', $pid, undef, undef, $message ) if $message eq 'Connection Timed Out';
|
||||
return ( 'close', $pid, undef, undef, $message ) if substr($message, 0, 20) eq 'click, disconnecting';
|
||||
return parse_line_cleanup( $line ) if substr($message, 0, 11) eq 'cleaning up';
|
||||
return ('init', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 19) eq 'Accepted connection';
|
||||
return ('connect', $pid, undef, undef, substr($message, 16))
|
||||
if substr($message, 0, 15) eq 'Connection from';
|
||||
return ('connect', $pid, undef, undef, substr($message, 16))
|
||||
if substr($message, 0, 8) eq 'connect ';
|
||||
return ('close', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 6) eq 'close ';
|
||||
return ('close', $pid, undef, undef, $message)
|
||||
if $message eq 'Connection Timed Out';
|
||||
return ('close', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 20) eq 'click, disconnecting';
|
||||
return parse_line_cleanup($line)
|
||||
if substr($message, 0, 11) eq 'cleaning up';
|
||||
|
||||
# lines seen less than once per connection
|
||||
return ( 'info', $pid, undef, undef, $message ) if $message eq 'spooling message to disk';
|
||||
return ('info', $pid, undef, undef, $message)
|
||||
if $message eq 'spooling message to disk';
|
||||
return ('reject', $pid, undef, undef, $message) if $message =~ /^[4|5]\d\d/;
|
||||
return ( 'reject', $pid, undef, undef, $message ) if substr($message, 0, 14) eq 'deny mail from';
|
||||
return ( 'reject', $pid, undef, undef, $message ) if substr($message, 0, 18) eq 'denysoft mail from';
|
||||
return ( 'info', $pid, undef, undef, $message ) if substr($message, 0, 15) eq 'Lost connection';
|
||||
return ( 'info', $pid, undef, undef, $message ) if $message eq 'auth success cleared naughty';
|
||||
return ( 'info', $pid, undef, undef, $message ) if substr($message, 0, 15) eq 'Running as user';
|
||||
return ( 'info', $pid, undef, undef, $message ) if substr($message, 0, 16) eq 'Loaded Qpsmtpd::';
|
||||
return ( 'info', $pid, undef, undef, $message ) if substr($message, 0, 24) eq 'Permissions on spool_dir';
|
||||
return ( 'info', $pid, undef, undef, $message ) if substr($message, 0, 13) eq 'Listening on ';
|
||||
return ( 'info', $pid, undef, undef, $message ) if substr($message, 0, 18) eq 'size_threshold set';
|
||||
return ( 'info', $pid, undef, undef, $message ) if substr($message, 0, 12) eq 'tls: ciphers';
|
||||
return ( 'error', $pid, undef, undef, $message ) if substr($message, 0, 22) eq 'of uninitialized value';
|
||||
return ( 'error', $pid, undef, undef, $message ) if substr($message, 0, 8) eq 'symbol "';
|
||||
return ( 'error', $pid, undef, undef, $message ) if substr($message, 0, 9) eq 'error at ';
|
||||
return ( 'error', $pid, undef, undef, $message ) if substr($message, 0, 15) eq 'Could not print';
|
||||
return ('reject', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 14) eq 'deny mail from';
|
||||
return ('reject', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 18) eq 'denysoft mail from';
|
||||
return ('info', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 15) eq 'Lost connection';
|
||||
return ('info', $pid, undef, undef, $message)
|
||||
if $message eq 'auth success cleared naughty';
|
||||
return ('info', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 15) eq 'Running as user';
|
||||
return ('info', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 16) eq 'Loaded Qpsmtpd::';
|
||||
return ('info', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 24) eq 'Permissions on spool_dir';
|
||||
return ('info', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 13) eq 'Listening on ';
|
||||
return ('info', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 18) eq 'size_threshold set';
|
||||
return ('info', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 12) eq 'tls: ciphers';
|
||||
return ('error', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 22) eq 'of uninitialized value';
|
||||
return ('error', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 8) eq 'symbol "';
|
||||
return ('error', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 9) eq 'error at ';
|
||||
return ('error', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 15) eq 'Could not print';
|
||||
|
||||
print "UNKNOWN LINE: $line\n";
|
||||
return ('unknown', $pid, undef, undef, $message);
|
||||
};
|
||||
}
|
||||
|
||||
sub parse_line_plugin {
|
||||
my ($line) = @_;
|
||||
@ -411,10 +437,10 @@ sub parse_line_plugin {
|
||||
}
|
||||
elsif ($plugin =~ /resolvable_fromhost/) {
|
||||
$message = 'pass' if $message =~ /^pass/;
|
||||
};
|
||||
}
|
||||
|
||||
return ('plugin', $pid, $hook, $plugin, $message);
|
||||
};
|
||||
}
|
||||
|
||||
sub parse_line_plugin_dspam {
|
||||
my $line = shift;
|
||||
@ -424,13 +450,13 @@ sub parse_line_plugin_dspam {
|
||||
|
||||
if ($message =~ /Innocent, (\d\.\d\d c)/) {
|
||||
$message = "pass, $1";
|
||||
};
|
||||
}
|
||||
if ($message =~ /Spam, (\d\.\d\d c)/) {
|
||||
$message = "fail, $1";
|
||||
};
|
||||
}
|
||||
|
||||
return ('plugin', $pid, $hook, $plugin, $message);
|
||||
};
|
||||
}
|
||||
|
||||
sub parse_line_plugin_spamassassin {
|
||||
my $line = shift;
|
||||
@ -440,13 +466,13 @@ sub parse_line_plugin_spamassassin {
|
||||
|
||||
if ($message =~ /pass, Ham, ([\d\-\.]+)\s/) {
|
||||
$message = "pass, $1";
|
||||
};
|
||||
}
|
||||
if ($message =~ /^fail, Spam,\s([\d\.]+)\s< 100/) {
|
||||
$message = "fail, $1";
|
||||
};
|
||||
}
|
||||
|
||||
return ('plugin', $pid, $hook, $plugin, $message);
|
||||
};
|
||||
}
|
||||
|
||||
sub parse_line_plugin_p0f {
|
||||
my $line = shift;
|
||||
@ -456,7 +482,7 @@ sub parse_line_plugin_p0f {
|
||||
|
||||
if (substr($message, -5, 5) eq 'hops)') {
|
||||
($message) = split(/\s\(/, $message);
|
||||
};
|
||||
}
|
||||
|
||||
$message = 'iOS' if $message =~ /^iOS/;
|
||||
$message = 'Solaris' if $message =~ /^Solaris/;
|
||||
@ -479,15 +505,16 @@ sub parse_line_plugin_p0f {
|
||||
$message = 'Netware' if $message =~ /Netware/i;
|
||||
|
||||
return ('plugin', $pid, $hook, $plugin, $message);
|
||||
};
|
||||
}
|
||||
|
||||
sub parse_line_cleanup {
|
||||
my ($line) = @_;
|
||||
|
||||
# @tai 85931 cleaning up after 3210
|
||||
my $pid = (split /\s+/, $line)[-1];
|
||||
$has_cleanup++;
|
||||
return ('cleanup', $pid, undef, undef, $line);
|
||||
};
|
||||
}
|
||||
|
||||
sub get_score {
|
||||
my $mess = shift;
|
||||
@ -498,8 +525,7 @@ sub get_score {
|
||||
return 2 if $mess =~ /^positive/;
|
||||
return 1 if $mess =~ /^skip/;
|
||||
return 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
sub get_db {
|
||||
|
||||
@ -507,7 +533,7 @@ sub get_db {
|
||||
or die DBIx::Simple->error;
|
||||
|
||||
return $db;
|
||||
};
|
||||
}
|
||||
|
||||
sub exec_query {
|
||||
my $query = shift;
|
||||
@ -516,12 +542,12 @@ sub exec_query {
|
||||
my @params;
|
||||
if (defined $params) {
|
||||
@params = ref $params eq 'ARRAY' ? @$params : $params;
|
||||
};
|
||||
}
|
||||
|
||||
my $err = "query failed: $query\n";
|
||||
if (scalar @params) {
|
||||
$err .= join(',', @params);
|
||||
};
|
||||
}
|
||||
|
||||
#warn "err: $err\n";
|
||||
if ($query =~ /INSERT INTO/) {
|
||||
@ -537,9 +563,9 @@ sub exec_query {
|
||||
elsif ($query =~ /DELETE/) {
|
||||
$db->query($query, @params) or die $err;
|
||||
return $db->query("SELECT ROW_COUNT()")->list;
|
||||
};
|
||||
}
|
||||
|
||||
my $r = $db->query($query, @params)->hashes or die $err;
|
||||
return $r;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -13,12 +13,13 @@ my $search = $ARGV[0];
|
||||
|
||||
if (!$search) {
|
||||
die "\nusage: $0 [ ip_address | PID ]\n\n";
|
||||
};
|
||||
}
|
||||
|
||||
if ($search =~ /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/) {
|
||||
|
||||
#print "it's an IP\n";
|
||||
$is_ip++;
|
||||
};
|
||||
}
|
||||
|
||||
open my $LOG, '<', $logfile or die "unable to open $logfile\n";
|
||||
|
||||
@ -34,13 +35,13 @@ if ( $is_ip ) { # look for the connection start message for the IP
|
||||
$ip_matches++;
|
||||
$search = $pid;
|
||||
$is_ip = 0;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
seek $LOG, 0, 0;
|
||||
die "no pid found for ip $search\n" if $is_ip;
|
||||
print "showing the last of $ip_matches connnections from $ARGV[0]\n";
|
||||
};
|
||||
}
|
||||
|
||||
print "showing QP message PID $search\n";
|
||||
|
||||
@ -49,24 +50,23 @@ while ( defined (my $line = <$LOG>) ) {
|
||||
my ($tai, $pid, $mess) = split /\s/, $line, 3;
|
||||
next if !$pid;
|
||||
print $mess if ($pid eq $search);
|
||||
};
|
||||
}
|
||||
close $LOG;
|
||||
|
||||
|
||||
sub get_qp_dir {
|
||||
foreach my $user (qw/ qpsmtpd smtpd /) {
|
||||
my ($homedir) = (getpwnam($user))[7] or next;
|
||||
|
||||
if (-d "$homedir/plugins") {
|
||||
return "$homedir";
|
||||
};
|
||||
}
|
||||
foreach my $s (qw/ smtpd qpsmtpd qpsmtpd-dev /) {
|
||||
if (-d "$homedir/$s/plugins") {
|
||||
return "$homedir/$s";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
if (-d "./plugins") {
|
||||
return Cwd::getcwd();
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
139
log/summarize
139
log/summarize
@ -15,9 +15,16 @@ my %hide_plugins = map { $_ => 1 } qw/ hostname /;
|
||||
my $qpdir = get_qp_dir();
|
||||
my $file = "$qpdir/log/main/current";
|
||||
populate_plugins_from_registry();
|
||||
my @sorted_plugins = sort { $plugins{$a}{id} <=> $plugins{$b}{id} } keys %plugins;
|
||||
my @sorted_plugins =
|
||||
sort { $plugins{$a}{id} <=> $plugins{$b}{id} } keys %plugins;
|
||||
|
||||
my $fh = File::Tail->new(name=>$file, interval=>1, maxinterval=>1, debug =>1, tail =>1000 );
|
||||
my $fh = File::Tail->new(
|
||||
name => $file,
|
||||
interval => 1,
|
||||
maxinterval => 1,
|
||||
debug => 1,
|
||||
tail => 1000
|
||||
);
|
||||
my $printed = 0;
|
||||
my $has_cleanup;
|
||||
|
||||
@ -69,7 +76,6 @@ my %formats3 = (
|
||||
'virus::clamdscan' => "%-3.3s",
|
||||
);
|
||||
|
||||
|
||||
while (defined(my $line = $fh->read)) {
|
||||
chomp $line;
|
||||
next if !$line;
|
||||
@ -82,10 +88,12 @@ while ( defined (my $line = $fh->read) ) {
|
||||
next if $type ne 'connect'; # ignore unless connect
|
||||
my ($host, $ip) = split /\s/, $message;
|
||||
$ip = substr $ip, 1, -1;
|
||||
foreach ( keys %seen_plugins, qw/ helo_host from to / ) { $pids{$pid}{$_} = ''; };
|
||||
foreach (keys %seen_plugins, qw/ helo_host from to /) {
|
||||
$pids{$pid}{$_} = '';
|
||||
}
|
||||
$pids{$pid}{ip} = $ip;
|
||||
$pids{$pid}{hostname} = $host if $host ne 'Unknown';
|
||||
};
|
||||
}
|
||||
|
||||
if ($type eq 'close') {
|
||||
next if $has_cleanup; # it'll get handled later
|
||||
@ -107,8 +115,8 @@ while ( defined (my $line = $fh->read) ) {
|
||||
}
|
||||
else {
|
||||
#print "ignoring subsequent hit on $plugin: $message\n";
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if ($plugin eq 'ident::geoip') {
|
||||
if (length $message < 3) {
|
||||
@ -120,9 +128,9 @@ while ( defined (my $line = $fh->read) ) {
|
||||
if ($distance) {
|
||||
$pids{$pid}{$plugin} = $gip;
|
||||
$pids{$pid}{distance} = $distance;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
elsif ($type eq 'reject') { }
|
||||
elsif ($type eq 'connect') { }
|
||||
@ -147,12 +155,12 @@ while ( defined (my $line = $fh->read) ) {
|
||||
else {
|
||||
# anything here is likely an unrecognized command
|
||||
#print "$message\n";
|
||||
};
|
||||
}
|
||||
}
|
||||
else {
|
||||
print "$type $pid $hook $plugin $message\n";
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
sub parse_line {
|
||||
my $line = shift;
|
||||
@ -161,33 +169,51 @@ sub parse_line {
|
||||
|
||||
# lines seen many times per connection
|
||||
return parse_line_plugin($line) if substr($message, 0, 1) eq '(';
|
||||
return ( 'dispatch', $pid, undef, undef, $message ) if substr($message, 0, 12) eq 'dispatching ';
|
||||
return ( 'response', $pid, undef, undef, $message ) if $message =~ /^[2|3]\d\d/;
|
||||
return ( 'tcpserver', $pid, undef, undef, undef ) if substr($pid, 0, 10) eq 'tcpserver:';
|
||||
return ('dispatch', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 12) eq 'dispatching ';
|
||||
return ('response', $pid, undef, undef, $message)
|
||||
if $message =~ /^[2|3]\d\d/;
|
||||
return ('tcpserver', $pid, undef, undef, undef)
|
||||
if substr($pid, 0, 10) eq 'tcpserver:';
|
||||
|
||||
# lines seen about once per connection
|
||||
return ( 'init', $pid, undef, undef, $message ) if substr($message, 0, 19) eq 'Accepted connection';
|
||||
return ( 'connect', $pid, undef, undef, substr( $message, 16) ) if substr($message, 0, 15) eq 'Connection from';
|
||||
return ( 'close', $pid, undef, undef, $message ) if substr($message, 0, 6) eq 'close ';
|
||||
return ( 'close', $pid, undef, undef, $message ) if substr($message, 0, 20) eq 'click, disconnecting';
|
||||
return parse_line_cleanup( $line ) if substr($message, 0, 11) eq 'cleaning up';
|
||||
return ('init', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 19) eq 'Accepted connection';
|
||||
return ('connect', $pid, undef, undef, substr($message, 16))
|
||||
if substr($message, 0, 15) eq 'Connection from';
|
||||
return ('close', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 6) eq 'close ';
|
||||
return ('close', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 20) eq 'click, disconnecting';
|
||||
return parse_line_cleanup($line)
|
||||
if substr($message, 0, 11) eq 'cleaning up';
|
||||
|
||||
# lines seen less than once per connection
|
||||
return ( 'info', $pid, undef, undef, $message ) if $message eq 'spooling message to disk';
|
||||
return ('info', $pid, undef, undef, $message)
|
||||
if $message eq 'spooling message to disk';
|
||||
return ('reject', $pid, undef, undef, $message) if $message =~ /^[4|5]\d\d/;
|
||||
return ( 'reject', $pid, undef, undef, $message ) if substr($message, 0, 14) eq 'deny mail from';
|
||||
return ( 'reject', $pid, undef, undef, $message ) if substr($message, 0, 18) eq 'denysoft mail from';
|
||||
return ( 'info', $pid, undef, undef, $message ) if substr($message, 0, 15) eq 'Lost connection';
|
||||
return ( 'info', $pid, undef, undef, $message ) if $message eq 'auth success cleared naughty';
|
||||
return ( 'info', $pid, undef, undef, $message ) if substr($message, 0, 15) eq 'Running as user';
|
||||
return ( 'info', $pid, undef, undef, $message ) if substr($message, 0, 16) eq 'Loaded Qpsmtpd::';
|
||||
return ( 'info', $pid, undef, undef, $message ) if substr($message, 0, 24) eq 'Permissions on spool_dir';
|
||||
return ( 'info', $pid, undef, undef, $message ) if substr($message, 0, 13) eq 'Listening on ';
|
||||
return ('reject', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 14) eq 'deny mail from';
|
||||
return ('reject', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 18) eq 'denysoft mail from';
|
||||
return ('info', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 15) eq 'Lost connection';
|
||||
return ('info', $pid, undef, undef, $message)
|
||||
if $message eq 'auth success cleared naughty';
|
||||
return ('info', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 15) eq 'Running as user';
|
||||
return ('info', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 16) eq 'Loaded Qpsmtpd::';
|
||||
return ('info', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 24) eq 'Permissions on spool_dir';
|
||||
return ('info', $pid, undef, undef, $message)
|
||||
if substr($message, 0, 13) eq 'Listening on ';
|
||||
|
||||
return ( 'err', $pid, undef, undef, $message ) if $line =~ /at [\S]+ line \d/; # generic perl error
|
||||
return ('err', $pid, undef, undef, $message)
|
||||
if $line =~ /at [\S]+ line \d/; # generic perl error
|
||||
print "UNKNOWN LINE: $line\n";
|
||||
return ('unknown', $pid, undef, undef, $message);
|
||||
};
|
||||
}
|
||||
|
||||
sub parse_line_plugin {
|
||||
my ($line) = @_;
|
||||
@ -200,25 +226,27 @@ sub parse_line_plugin {
|
||||
$plugin =~ s/:$//;
|
||||
if ($plugin =~ /_3a/) {
|
||||
($plugin) = split /_3a/, $plugin; # trim :N off the plugin log entry
|
||||
};
|
||||
}
|
||||
$plugin =~ s/_2d/-/g;
|
||||
|
||||
$plugin = $plugin_aliases{$plugin} if $plugin_aliases{$plugin}; # map alias to master
|
||||
$plugin = $plugin_aliases{$plugin}
|
||||
if $plugin_aliases{$plugin}; # map alias to master
|
||||
if ($hook eq '(queue)') {
|
||||
($pid) = $message =~ /\(for ([\d]+)\)\s/;
|
||||
$message = 'pass';
|
||||
};
|
||||
}
|
||||
|
||||
return ('plugin', $pid, $hook, $plugin, $message);
|
||||
};
|
||||
}
|
||||
|
||||
sub parse_line_cleanup {
|
||||
my ($line) = @_;
|
||||
|
||||
# @tai 85931 cleaning up after 3210
|
||||
my $pid = (split /\s+/, $line)[-1];
|
||||
$has_cleanup++;
|
||||
return ('cleanup', $pid, undef, undef, $line);
|
||||
};
|
||||
}
|
||||
|
||||
sub print_auto_format {
|
||||
my ($pid, $line) = @_;
|
||||
@ -231,15 +259,15 @@ sub print_auto_format {
|
||||
if (defined $pids{$pid}{$plugin}) {
|
||||
if (!$seen_plugins{$plugin}) { # first time seeing this plugin
|
||||
$printed = 0; # force header print
|
||||
};
|
||||
}
|
||||
$seen_plugins{$plugin}++;
|
||||
};
|
||||
}
|
||||
|
||||
next if !$seen_plugins{$plugin}; # hide unused plugins
|
||||
if ($hide_plugins{$plugin}) { # user doesn't want to see
|
||||
delete $pids{$pid}{$plugin};
|
||||
next;
|
||||
};
|
||||
}
|
||||
|
||||
if (defined $pids{$pid}{helo_host} && $plugin =~ /helo/) {
|
||||
$format .= " %-18.18s";
|
||||
@ -255,7 +283,7 @@ sub print_auto_format {
|
||||
$format .= " %-20.20s";
|
||||
push @values, delete $pids{$pid}{to};
|
||||
push @headers, 'RCPT TO';
|
||||
};
|
||||
}
|
||||
|
||||
$format .= $formats3{$plugin} ? " $formats3{$plugin}" : " %-10.10s";
|
||||
|
||||
@ -264,15 +292,16 @@ sub print_auto_format {
|
||||
}
|
||||
else {
|
||||
push @values, '';
|
||||
};
|
||||
push @headers, ($plugins{$plugin}{abb3} ? $plugins{$plugin}{abb3} : $plugin);
|
||||
}
|
||||
push @headers,
|
||||
($plugins{$plugin}{abb3} ? $plugins{$plugin}{abb3} : $plugin);
|
||||
}
|
||||
$format .= "\n";
|
||||
printf("\n$format", @headers) if (!$printed || $printed % 20 == 0);
|
||||
printf($format, @values);
|
||||
print Data::Dumper::Dumper($pids{$pid}) if keys %{$pids{$pid}};
|
||||
$printed++;
|
||||
};
|
||||
}
|
||||
|
||||
sub show_symbol {
|
||||
my $mess = shift;
|
||||
@ -288,7 +317,7 @@ sub show_symbol {
|
||||
return ' !' if $mess =~ /^error[,:\s]/i;
|
||||
$mess =~ s/\s\s/ /g;
|
||||
return $mess;
|
||||
};
|
||||
}
|
||||
|
||||
sub get_qp_dir {
|
||||
foreach my $user (qw/ qpsmtpd smtpd /) {
|
||||
@ -296,24 +325,24 @@ sub get_qp_dir {
|
||||
|
||||
if (-d "$homedir/plugins") {
|
||||
return "$homedir";
|
||||
};
|
||||
}
|
||||
foreach my $s (qw/ smtpd qpsmtpd qpsmtpd-dev /) {
|
||||
if (-d "$homedir/$s/plugins") {
|
||||
return "$homedir/$s";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
if (-d "./plugins") {
|
||||
return Cwd::getcwd();
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
sub populate_plugins_from_registry {
|
||||
|
||||
my $file = "$qpdir/plugins/registry.txt";
|
||||
if (!-f $file) {
|
||||
die "unable to find plugin registry\n";
|
||||
};
|
||||
}
|
||||
|
||||
open my $F, '<', $file;
|
||||
while (defined(my $line = <$F>)) {
|
||||
@ -327,7 +356,7 @@ sub populate_plugins_from_registry {
|
||||
$plugins{$name}{aliases} = $aliases;
|
||||
foreach my $a (split /,/, $aliases) {
|
||||
$plugin_aliases{$a} = $name;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
22
log/watch
22
log/watch
@ -11,12 +11,18 @@ use File::Tail;
|
||||
|
||||
my $dir = get_qp_dir() or die "unable to find QP home dir";
|
||||
my $file = "$dir/log/main/current";
|
||||
my $fh = File::Tail->new(name=>$file, interval=>1, maxinterval=>1, debug =>1, tail =>300 );
|
||||
my $fh = File::Tail->new(
|
||||
name => $file,
|
||||
interval => 1,
|
||||
maxinterval => 1,
|
||||
debug => 1,
|
||||
tail => 300
|
||||
);
|
||||
|
||||
while (defined(my $line = $fh->read)) {
|
||||
my (undef, $line) = split /\s/, $line, 2; # strip off tai timestamps
|
||||
print $line;
|
||||
};
|
||||
}
|
||||
|
||||
sub get_qp_dir {
|
||||
foreach my $user (qw/ qpsmtpd smtpd /) {
|
||||
@ -24,15 +30,15 @@ sub get_qp_dir {
|
||||
|
||||
if (-d "$homedir/plugins") {
|
||||
return "$homedir";
|
||||
};
|
||||
}
|
||||
foreach my $s (qw/ smtpd qpsmtpd qpsmtpd-dev /) {
|
||||
if (-d "$homedir/$s/plugins") {
|
||||
return "$homedir/$s";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
if (-d "./plugins") {
|
||||
return Cwd::getcwd();
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user